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