hotspot/src/share/vm/prims/jvmtiEnv.cpp
// class_count - pre-checked to be greater than or equal to 0
// classes - pre-checked for NULL
jvmtiError
JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
{- -------------------------------------------
(1)
---------------------------------------- -}
//TODO: add locking
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
int index;
JavaThread* current_thread = JavaThread::current();
ResourceMark rm(current_thread);
{- -------------------------------------------
(1) 集めたクラス情報を入れておくための配列を確保する.
(確保に失敗したら JVMTI_ERROR_OUT_OF_MEMORY エラーをリターン)
---------------------------------------- -}
jvmtiClassDefinition* class_definitions =
NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count);
NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY);
{- -------------------------------------------
(1) (以下の for ループで指定されたクラス数分だけループし, クラス情報を集めていく)
---------------------------------------- -}
for (index = 0; index < class_count; index++) {
{- -------------------------------------------
(1)
---------------------------------------- -}
HandleMark hm(current_thread);
jclass jcls = classes[index];
oop k_mirror = JNIHandles::resolve_external_guard(jcls);
if (k_mirror == NULL) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (!k_mirror->is_a(SystemDictionary::Class_klass())) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (java_lang_Class::is_primitive(k_mirror)) {
return JVMTI_ERROR_UNMODIFIABLE_CLASS;
}
klassOop k_oop = java_lang_Class::as_klassOop(k_mirror);
KlassHandle klass(current_thread, k_oop);
jint status = klass->jvmti_class_status();
if (status & (JVMTI_CLASS_STATUS_ERROR)) {
return JVMTI_ERROR_INVALID_CLASS;
}
if (status & (JVMTI_CLASS_STATUS_ARRAY)) {
return JVMTI_ERROR_UNMODIFIABLE_CLASS;
}
instanceKlassHandle ikh(current_thread, k_oop);
{- -------------------------------------------
(1.1) キャッシュしている内容がなければ, JvmtiClassFileReconstituter でクラス情報を復元する.
(VM_RedefineClasses 内でもキャッシュがセットされているので, 同じクラスについては最大でも一回しか Reconstitute されない?? #TODO)
---------------------------------------- -}
if (ikh->get_cached_class_file_bytes() == NULL) {
// not cached, we need to reconstitute the class file from VM representation
constantPoolHandle constants(current_thread, ikh->constants());
ObjectLocker ol(constants, current_thread); // lock constant pool while we query it
{- -------------------------------------------
(1.1.1) JvmtiClassFileReconstituter オブジェクトを生成し (生成に失敗したらエラー),
JvmtiClassFileReconstituter::class_file_size() と
JvmtiClassFileReconstituter::class_file_bytes() を呼んで,
クラスファイル情報を取得する.
---------------------------------------- -}
JvmtiClassFileReconstituter reconstituter(ikh);
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
return reconstituter.get_error();
}
class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size();
class_definitions[index].class_bytes = (unsigned char*)
reconstituter.class_file_bytes();
{- -------------------------------------------
(1.1) もしキャッシュしている内容があれば, それを使う.
---------------------------------------- -}
} else {
// it is cached, get it from the cache
class_definitions[index].class_byte_count = ikh->get_cached_class_file_len();
class_definitions[index].class_bytes = ikh->get_cached_class_file_bytes();
}
{- -------------------------------------------
(1)
---------------------------------------- -}
class_definitions[index].klass = jcls;
}
{- -------------------------------------------
(1) 集めた情報を VM_RedefineClasses に引き渡して RedefineClasses の処理に引き継ぐ.
---------------------------------------- -}
VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
VMThread::execute(&op);
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return (op.check_error());
} /* end RetransformClasses */
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.