CDS and JVM-TI agent questions and crash

Jiangli Zhou jiangli.zhou at oracle.com
Mon Oct 15 21:59:20 UTC 2018


Hi Michael,

On 10/15/18 2:14 PM, Michael Rasmussen wrote:
>> I logged issue in JDK-8212200,
>> https://bugs.openjdk.java.net/browse/JDK-8212200
>> Thanks,
>> Jiangli
> Hi Jiangli,
>
> Thanks -- though regarding your comment there, I don't know if it only applies when changing Object's bytes?
> I did a small test (attached below) with adding a default method to Serializable, and it crashes as well, though differently -- don't know if what Volker mentioned fixes this though.
>
> Running the below with CDS off, I get:
> $ ../jdk/bin/java -Xshare:off -agentpath:./libagent.so Test.java
> public default java.lang.Object java.io.Serializable._$_$_blah()
>
> With it on, I get the following crash:
> $ ../jdk/bin/java -Xshare:on -agentpath:./libagent.so Test.java
> #  Internal Error (.../src/hotspot/share/classfile/javaClasses.cpp:667), pid=277, tid=278
> #  assert(java_string->klass() == SystemDictionary::String_klass()) failed: must be java_string
This appears to be a bug when archived java.lang.String class is not 
used (String class is dynamically loaded in this case) but the mapped 
compact string hash stable is still in use. We need to detect such case 
and disable the shared compact string table. Thanks for reporting this 
issue. I've added it to the JDK-8212200 report as well.

One simple alternative fix is to disable sharing when some events (like 
CFLH) were enabled. This in fact was the behavior before JDK 9. In JDK 
9, we enabled CDS for debugging. Looks like there are corner cases that 
are not uncovered by our testing. I'd like to seek opinions and feedback 
on the importance of supporting debugging with CDS enabled.

Thanks!

Jiangli
>
> /Michael
>
> Stack trace:
> V  [libjvm.so+0xe80ea5]  java_lang_String::equals(oop, unsigned short*, int)+0x85
> V  [libjvm.so+0x9e6e44]  CompactHashtable<oop, char>::decode_entry(CompactHashtable<oop, char>*, unsigned int, char const*, int)+0x54
> V  [libjvm.so+0x167fae6]  StringTable::lookup_shared(unsigned short*, int, unsigned int)+0x166
> V  [libjvm.so+0x16801df]  StringTable::intern(Handle, unsigned short*, int, Thread*)+0x6f
> V  [libjvm.so+0x16802e3]  StringTable::intern(Symbol*, Thread*)+0x53
> V  [libjvm.so+0xae9921]  ConstantPool::uncached_string_at(int, Thread*)+0x31
> V  [libjvm.so+0xc4426c]  fieldDescriptor::string_initial_value(Thread*) const+0x9c
> V  [libjvm.so+0xe88056]  initialize_static_field(fieldDescriptor*, Handle, Thread*)+0x1c6
> V  [libjvm.so+0xe23819]  InstanceKlass::do_local_static_fields(void (*)(fieldDescriptor*, Handle, Thread*), Handle, Thread*)+0xd9
> V  [libjvm.so+0xe70157]  java_lang_Class::initialize_mirror_fields(Klass*, Handle, Handle, Thread*)+0x117
> V  [libjvm.so+0xe723c3]  java_lang_Class::create_mirror(Klass*, Handle, Handle, Handle, Thread*)+0x723
> V  [libjvm.so+0x95b8fd]  ClassFileParser::fill_instance_klass(InstanceKlass*, bool, Thread*)+0x1c8d
> V  [libjvm.so+0x95c12f]  ClassFileParser::create_instance_klass(bool, Thread*)+0x5f
> V  [libjvm.so+0x118e5f5]  KlassFactory::create_from_stream(ClassFileStream*, Symbol*, ClassLoaderData*, Handle, InstanceKlass const*, GrowableArray<Handle>*, Thread*)+0x615
> V  [libjvm.so+0x96b76c]  ClassLoader::load_class(Symbol*, bool, Thread*)+0x1bc
> V  [libjvm.so+0x171a3e6]  SystemDictionary::load_instance_class(Symbol*, Handle, Thread*)+0x5f6
> V  [libjvm.so+0x1718139]  SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle, Handle, Thread*)+0xa69
> V  [libjvm.so+0x1718662]  SystemDictionary::resolve_or_null(Symbol*, Handle, Handle, Thread*)+0x42
> V  [libjvm.so+0x17187de]  SystemDictionary::resolve_or_fail(Symbol*, Handle, Handle, bool, Thread*)+0x1e
> V  [libjvm.so+0x1718991]  SystemDictionary::initialize_wk_klass(SystemDictionary::WKID, int, Thread*)+0x151
> V  [libjvm.so+0x1718af1]  SystemDictionary::initialize_wk_klasses_until(SystemDictionary::WKID, SystemDictionary::WKID&, Thread*)+0x61
> V  [libjvm.so+0x1718d33]  SystemDictionary::initialize_preloaded_classes(Thread*)+0x153
> V  [libjvm.so+0x17190ea]  SystemDictionary::initialize(Thread*)+0x21a
> V  [libjvm.so+0x17a8140]  Universe::genesis(Thread*)+0x5f0
> V  [libjvm.so+0x17a8b5c]  universe2_init()+0x2c
> V  [libjvm.so+0xe1e558]  init_globals()+0xa8
> V  [libjvm.so+0x1766d17]  Threads::create_vm(JavaVMInitArgs*, bool*)+0x2d7
>
>
> Sample code:
> /* --- snip ---- */
> #include <string.h>
> #include <jni.h>
> #include <jvmti.h>
>
> static char *serializable_class_name = "java/io/Serializable";
> /*
>    public interface java.io.Serializable {
>      default Object _$_$_blah() { return this; }
>    }
> */
> static jbyte serializable_class_bytes[] = {
> 	202, 254, 186, 190,   0,   0,   0,  55,   0,  10,   1,   0,  20, 106,  97, 118,
> 	 97,  47, 105, 111,  47,  83, 101, 114, 105,  97, 108, 105, 122,  97,  98, 108,
> 	101,   7,   0,   1,   1,   0,  16, 106,  97, 118,  97,  47, 108,  97, 110, 103,
> 	 47,  79,  98, 106, 101,  99, 116,   7,   0,   3,   1,   0,  17,  83, 101, 114,
> 	105,  97, 108, 105, 122,  97,  98, 108, 101,  46, 106,  97, 118,  97,   1,   0,
> 	  9,  95,  36,  95,  36,  95,  98, 108,  97, 104,   1,   0,  20,  40,  41,  76,
> 	106,  97, 118,  97,  47, 108,  97, 110, 103,  47,  79,  98, 106, 101,  99, 116,
> 	 59,   1,   0,   4,  67, 111, 100, 101,   1,   0,  10,  83, 111, 117, 114,  99,
> 	101,  70, 105, 108, 101,   6,   1,   0,   2,   0,   4,   0,   0,   0,   0,   0,
> 	  1,   0,   1,   0,   6,   0,   7,   0,   1,   0,   8,   0,   0,   0,  14,   0,
> 	  1,   0,   1,   0,   0,   0,   2,  42, 176,   0,   0,   0,   0,   0,   1,   0,
> 	  9,   0,   0,   0,   2,   0,   5
> };
> static jsize serializable_class_bytes_len = 183;
>
> void JNICALL callback_ClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env,
> 	jclass class_being_redefined, jobject loader, const char* name, jobject protection_domain,
> 	jint class_data_len, const unsigned char* class_data,
> 	jint* new_class_data_len, unsigned char** new_class_data) {
>
> 	if (strcmp(serializable_class_name, name) == 0) {
> 		*new_class_data_len = serializable_class_bytes_len;
> 		(*jvmti)->Allocate(jvmti, *new_class_data_len, new_class_data);
> 		memcpy(*new_class_data, serializable_class_bytes, *new_class_data_len);
> 	}
> }
>
> JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
> 	jvmtiEnv *jvmti;
> 	jint rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_9);
> 	
> 	jvmtiCapabilities caps;
> 	memset(&caps, 0, sizeof(caps));
>
> 	caps.can_redefine_classes = 1;
> 	caps.can_generate_all_class_hook_events = 1;
> 	caps.can_generate_early_vmstart = 1;
> 	caps.can_generate_early_class_hook_events = 1;
>
> 	(*jvmti)->AddCapabilities(jvmti, &caps);
>
> 	jvmtiEventCallbacks callbacks;
> 	memset(&callbacks, 0, sizeof(callbacks));
> 	callbacks.ClassFileLoadHook = &callback_ClassFileLoadHook;
> 	(*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
> 	(*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
>
> 	return 0;
> }
> /* ---- snap --- */
> import java.io.Serializable;
> import java.util.stream.Stream;
>
> public class Test {
>    public static void main(String[] args) {
>      Stream.of(Serializable.class.getDeclaredMethods()).forEach(System.out::println);
>    }
> }
> /* ---- snude ---- */



More information about the hotspot-dev mailing list