voidpost_to_env(JvmtiEnv* env, bool caching_needed){ unsignedchar *new_data = NULL; jint new_len = 0; /*......*/ JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader, _h_protection_domain, _h_class_being_redefined); JvmtiJavaThreadEventTransition jet(_thread); JNIEnv* jni_env = (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)? NULL : jem.jni_env(); jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook; if (callback != NULL) { (*callback)(env->jvmti_external(), jni_env, jem.class_being_redefined(), jem.jloader(), jem.class_name(), jem.protection_domain(), _curr_len, _curr_data, &new_len, &new_data); } if (new_data != NULL) { // this agent has modified class data. if (caching_needed && *_cached_class_file_ptr == NULL) { // data has been changed by the new retransformable agent // and it hasn't already been cached, cache it JvmtiCachedClassFileData *p; p = (JvmtiCachedClassFileData *)os::malloc( offset_of(JvmtiCachedClassFileData, data) + _curr_len, mtInternal); if (p == NULL) { vm_exit_out_of_memory(offset_of(JvmtiCachedClassFileData, data) + _curr_len, OOM_MALLOC_ERROR, "unable to allocate cached copy of original class bytes"); } p->length = _curr_len; memcpy(p->data, _curr_data, _curr_len); *_cached_class_file_ptr = p; }
if (_curr_data != *_data_ptr) { // curr_data is previous agent modified class data. // And this has been changed by the new agent so // we can delete it now. _curr_env->Deallocate(_curr_data); }
// Class file data has changed by the current agent. _curr_data = new_data; _curr_len = new_len; // Save the current agent env we need this to deallocate the // memory allocated by this agent. _curr_env = env; } } /*......*/ };
[Remote::java ]-> %help Available commands: %resume(0) - resume execution of the spawned process %load(1) - Load an additional script and reload the current REPL state %reload(0) - reload (i.e. rerun) the script that was given as an argument to the REPL %unload(0) - no description %autoperform(1) - receive on/off as first and only argument, when switched on will wrap any REPL code with Java.performNow() %autoreload(1) - disable or enable auto reloading of script files %exec(1) - execute the given file path in the context of the currently loaded scripts %time(1+) - measure the execution time of the given expression and print it to the screen %help(0) - print a list of available REPL commands
h_name 是加载的类名,我们需要利用这个参数还原class文件名(虽然也可以全部dump完用框架读字节码的类名),但它不是一个标准的C字符串类型。而是一个 Symbol 对象,它是JVM 内部用来表示字符串的结构。
稍微看一下这个结构体
classSymbolBase :public MetaspaceObj { public: ATOMIC_SHORT_PAIR( volatileshort _refcount, // needs atomic operation unsignedshort _length // number of UTF8 characters in the symbol (does not need atomic op) ); int _identity_hash; };