JVM之类的热替换原理解读,小米Java校招面试

// src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c

JNIEXPORT void JNICALL

Java_sun_instrument_InstrumentationImpl_retransformClasses0

(JNIEnv * jnienv, jobject implThis, jlong agent, jobjectArray classes) {

retransformClasses(jnienv, (JPLISAgent*)(intptr_t)agent, classes);

}




retransformClasses()最后会调用到 jvmtiEnv.cpp中的RetransformClasses



// src/hotspot/share/prims/jvmtiEnv.cpp

jvmtiError

JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {

int index;

JavaThread* current_thread = JavaThread::current();

ResourceMark rm(current_thread);

jvmtiClassDefinition* class_definitions =

                        NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count);

for (index = 0; index < class_count; index++) {

HandleMark hm(current_thread);



jclass jcls = classes[index];

oop k_mirror = JNIHandles::resolve_external_guard(jcls);

......

Klass* klass = java_lang_Class::as_Klass(k_mirror);



jint status = klass->jvmti_class_status();

if (status & (JVMTI_CLASS_STATUS_ERROR)) {

  return JVMTI_ERROR_INVALID_CLASS;

}



InstanceKlass* ik = InstanceKlass::cast(klass);

if (ik->get_cached_class_file_bytes() == NULL) {

  JvmtiClassFileReconstituter reconstituter(ik);

  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();

} else {

  // it is cached, get it from the cache

  class_definitions[index].class_byte_count = ik->get_cached_class_file_len();

  class_definitions[index].class_bytes      = ik->get_cached_class_file_bytes();

}

class_definitions[index].klass              = jcls;

}

VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);

VMThread::execute(&op);

return (op.check_error());

}




上面这段主要干了两件事:



(1) 根据java层的Class对象,找到JVM层的类实例InstanceKlass,并获取类的字节码,存放在class\_definitions数组中。因为可以一次替换多个类,所以这里加了一个循环体,遍历每个要修改的类。



(2) 调用VMThread::execute(&op),进入下一步。



VMThread::execute(&op
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值