# HG changeset patch # User lfoltan # Date 1461244984 14400 # Node ID 8731fa11f766491561e78f6133e357c8315412cd # Parent 89b93eb018fbde35961a8e6d3d59f3a22a65af14 8152949: Jigsaw crash when Klass in _fixup_module_field_list is unloaded Summary: During start up anonymous classes must be kept alive until after their mirror's module field is patched with java.base Reviewed-by: coleenp, hseigel Contributed-by: per.liden@oracle.com, stefan.karlsson@oracle.com diff -r 89b93eb018fb -r 8731fa11f766 hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Tue Apr 19 14:53:33 2016 +0200 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Apr 21 09:23:04 2016 -0400 @@ -84,7 +84,7 @@ // An anonymous class loader data doesn't have anything to keep // it from being unloaded during parsing of the anonymous class. // The null-class-loader should always be kept alive. - _keep_alive(is_anonymous || h_class_loader.is_null()), + _keep_alive((is_anonymous || h_class_loader.is_null()) ? 1 : 0), _metaspace(NULL), _unloading(false), _klasses(NULL), _modules(NULL), _packages(NULL), _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), @@ -114,6 +114,21 @@ return (int) Atomic::cmpxchg(1, &_claimed, 0) == 0; } +// Anonymous classes have their own ClassLoaderData that is marked to keep alive +// while the class is being parsed, and if the class appears on the module fixup list. +// Due to the uniqueness that no other class shares the anonymous class' name or +// ClassLoaderData, no other non-GC thread has knowledge of the anonymous class while +// it is being defined, therefore _keep_alive is not volatile or atomic. +void ClassLoaderData::inc_keep_alive() { + assert(_keep_alive >= 0, "Invalid keep alive count"); + _keep_alive++; +} + +void ClassLoaderData::dec_keep_alive() { + assert(_keep_alive > 0, "Invalid keep alive count"); + _keep_alive--; +} + void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) { if (must_claim && !claim()) { return; diff -r 89b93eb018fb -r 8731fa11f766 hotspot/src/share/vm/classfile/classLoaderData.hpp --- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Tue Apr 19 14:53:33 2016 +0200 +++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Apr 21 09:23:04 2016 -0400 @@ -175,8 +175,11 @@ // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. bool _unloading; // true if this class loader goes away - bool _keep_alive; // if this CLD is kept alive without a keep_alive_object(). bool _is_anonymous; // if this CLD is for an anonymous class + int _keep_alive; // if this CLD is kept alive without a keep_alive_object(). + // Currently used solely for anonymous classes. + // _keep_alive does not need to be volatile or + // atomic since there is one unique CLD per anonymous class. volatile int _claimed; // true if claimed, for example during GC traces. // To avoid applying oop closure more than once. // Has to be an int because we cas it. @@ -224,7 +227,7 @@ bool claim(); void unload(); - bool keep_alive() const { return _keep_alive; } + bool keep_alive() const { return _keep_alive > 0; } void classes_do(void f(Klass*)); void loaded_classes_do(KlassClosure* klass_closure); void classes_do(void f(InstanceKlass*)); @@ -286,8 +289,8 @@ return _unloading; } - // Used to make sure that this CLD is not unloaded. - void set_keep_alive(bool value) { _keep_alive = value; } + void inc_keep_alive(); + void dec_keep_alive(); inline unsigned int identity_hash() const; diff -r 89b93eb018fb -r 8731fa11f766 hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Apr 19 14:53:33 2016 +0200 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Apr 21 09:23:04 2016 -0400 @@ -852,6 +852,7 @@ new (ResourceObj::C_HEAP, mtClass) GrowableArray(500, true); set_fixup_module_field_list(list); } + k->class_loader_data()->inc_keep_alive(); fixup_module_field_list()->push(k()); } } else { diff -r 89b93eb018fb -r 8731fa11f766 hotspot/src/share/vm/classfile/moduleEntry.cpp --- a/hotspot/src/share/vm/classfile/moduleEntry.cpp Tue Apr 19 14:53:33 2016 +0200 +++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp Thu Apr 21 09:23:04 2016 -0400 @@ -354,6 +354,7 @@ Thread* THREAD = Thread::current(); KlassHandle kh(THREAD, k); java_lang_Class::fixup_module_field(kh, module_handle); + k->class_loader_data()->dec_keep_alive(); } delete java_lang_Class::fixup_module_field_list(); diff -r 89b93eb018fb -r 8731fa11f766 hotspot/src/share/vm/classfile/modules.cpp --- a/hotspot/src/share/vm/classfile/modules.cpp Tue Apr 19 14:53:33 2016 +0200 +++ b/hotspot/src/share/vm/classfile/modules.cpp Thu Apr 21 09:23:04 2016 -0400 @@ -277,6 +277,11 @@ { MutexLocker m1(Module_lock, THREAD); + if (ModuleEntryTable::javabase_defined()) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Module java.base is already defined"); + } + // Verify that all java.base packages created during bootstrapping are in // pkg_list. If any are not in pkg_list, than a non-java.base class was // loaded erroneously pre java.base module definition. diff -r 89b93eb018fb -r 8731fa11f766 hotspot/src/share/vm/prims/unsafe.cpp --- a/hotspot/src/share/vm/prims/unsafe.cpp Tue Apr 19 14:53:33 2016 +0200 +++ b/hotspot/src/share/vm/prims/unsafe.cpp Thu Apr 21 09:23:04 2016 -0400 @@ -934,7 +934,7 @@ // this point. The mirror and any instances of this class have to keep // it alive afterwards. if (anon_klass() != NULL) { - anon_klass->class_loader_data()->set_keep_alive(false); + anon_klass->class_loader_data()->dec_keep_alive(); } // let caller initialize it as needed...