JavaClassRegistry.st
branchdevelopment
changeset 2948 af30789878ce
parent 2942 c39cbf09ea3d
child 2952 ff6465e92d95
--- a/JavaClassRegistry.st	Sat Nov 23 10:19:14 2013 +0000
+++ b/JavaClassRegistry.st	Tue Nov 26 21:19:39 2013 +0000
@@ -21,7 +21,7 @@
 "{ Package: 'stx:libjava' }"
 
 Object subclass:#JavaClassRegistry
-	instanceVariableNames:'vm loaders notifier'
+	instanceVariableNames:'vm loaders notifier lock'
 	classVariableNames:''
 	poolDictionaries:'JavaVMData'
 	category:'Languages-Java-Support'
@@ -107,26 +107,41 @@
 classForName: className loader: classLoader ifAbsentPut: block 
     "Get class loaded by classLoader from registry. if absent block is evaluated and resulting class in registered in registry, "
     
-    | class |
+    | class synchronizer |
+
     self assert: (className includes: $.) not.
-     "if class is already registered with the same cl, just return it"
-    class := self classNamed: className loader: classLoader.
-    class notNil ifTrue: [ ^ class ].
-    "if java vm is booted, nil class loader means system class loader, lets check it too"
-    (vm notNil and:[vm booted and: [classLoader isNil]]) ifTrue: [
-        class := self classNamed: className loader: vm systemClassLoader. 
-        class notNil ifTrue: [^class]
-    ].
-     "otherwise evaluate block"
-    class := block value.
-    class notNil ifTrue: [
-    self registerClass: class.].
-    ^ class.
+
+    "/ Temporary workaround for race-condition when multiple threads are
+    "/ loading same class. Note that ClassLoader.loadClass() / loadClassInternal()
+    "/ is itself sychronized so we have to synchronize iff and only iff
+    "/ we're loading for primordial class loader. If we synchronize
+    "/ event non-primordial loaders, we risk a deadlock. Very hacky...
+
+    synchronizer := classLoader isNil 
+                        ifTrue:[ [:whatToDo | lock critical: whatToDo ] ]
+                        ifFalse:[ [:whatToDo | whatToDo value ] ].
+
+    synchronizer value:[
+        "If class is already registered with the same cl, just return it"
+        class := self classNamed: className loader: classLoader.
+        class isNil ifTrue:[
+            "If java vm is booted, nil class loader means system class loader, lets check it too"
+            (vm notNil and:[vm booted and: [classLoader isNil]]) ifTrue: [
+                class := self classNamed: className loader: vm systemClassLoader. 
+            ].
+        ].
+        class isNil ifTrue:[
+            "Otherwise evaluate block"
+            class := block value.
+            class notNil ifTrue: [ self registerClass: class ].
+        ].
+     ].
+    ^ class
 
     "Created: / 21-10-2011 / 12:00:30 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
     "Created: / 23-10-2011 / 11:36:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 02-11-2011 / 17:29:20 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
-    "Modified (format): / 24-01-2013 / 11:19:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 26-11-2013 / 20:18:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 classNamed: className
@@ -284,8 +299,9 @@
                     named: 'Java class registry notifier'
                     on:[:typeAndClass|Smalltalk changed: typeAndClass first with: typeAndClass second].
     notifier priority: Processor userBackgroundPriority - 1.
+    lock := RecursionLock new.
 
-    "Modified: / 08-02-2013 / 00:58:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (format): / 22-11-2013 / 11:08:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 setVM: aJavaVM