--- 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