private static bool CheckInitialized(MemberName member) { Class defc = member.DeclaringClass; WeakReference <Thread> @ref = EnsureInitialized.INSTANCE.Get(defc); if (@ref == null) { return(true); // the final state } Thread clinitThread = @ref.get(); // Somebody may still be running defc.<clinit>. if (clinitThread == Thread.CurrentThread) { // If anybody is running defc.<clinit>, it is this thread. if (UNSAFE.shouldBeInitialized(defc)) { // Yes, we are running it; keep the barrier for now. return(false); } } else { // We are in a random thread. Block. UNSAFE.ensureClassInitialized(defc); } assert(!UNSAFE.shouldBeInitialized(defc)); // put it into the final state EnsureInitialized.INSTANCE.Remove(defc); return(true); }
/*non-public*/ internal static bool ShouldBeInitialized(MemberName member) { switch (member.ReferenceKind) { case REF_invokeStatic: case REF_getStatic: case REF_putStatic: case REF_newInvokeSpecial: break; default: // No need to initialize the class on this kind of member. return(false); } Class cls = member.DeclaringClass; if (cls == typeof(ValueConversions) || cls == typeof(MethodHandleImpl) || cls == typeof(Invokers)) { // These guys have lots of <clinit> DMH creation but we know // the MHs will not be used until the system is booted. return(false); } if (VerifyAccess.isSamePackage(typeof(MethodHandle), cls) || VerifyAccess.isSamePackage(typeof(ValueConversions), cls)) { // It is a system class. It is probably in the process of // being initialized, but we will help it along just to be safe. if (UNSAFE.shouldBeInitialized(cls)) { UNSAFE.ensureClassInitialized(cls); } return(false); } return(UNSAFE.shouldBeInitialized(cls)); }
protected internal override WeakReference <Thread> ComputeValue(Class type) { UNSAFE.ensureClassInitialized(type); if (UNSAFE.shouldBeInitialized(type)) // If the previous call didn't block, this can happen. // We are executing inside <clinit>. { return(new WeakReference <>(Thread.CurrentThread)); } return(null); }