Fixes for class unloadfing: unload inner classes first.
--- a/JavaClassRegistry.st Mon Aug 11 01:55:40 2014 +0100
+++ b/JavaClassRegistry.st Mon Aug 11 09:46:49 2014 +0100
@@ -402,23 +402,26 @@
unregisterClass: oldClass
| classes |
- "/ First. remove the class from system dictionary
- "/ and from registry so nobody could resolve it.
- self unregisterClassInSmalltalk: oldClass notify: true.
classes := loaders at: oldClass classLoader ifAbsent: nil.
classes notNil ifTrue:[
"/ Check if the class is there, it could be removed meanwhile...
(classes includesKey: oldClass binaryName) ifTrue:[
- classes removeKey: oldClass binaryName.
"/ Now, invalidate references and unload all dependent clases
"/ (JavaClassReloader will unload them by recursively call #unregisterClass:
JavaClassReloader unload: oldClass.
+ "/ Now remove it from class registry...
+ classes removeKey: oldClass binaryName.
+ "/ ...from class loader...
+ self unregisterClassInClassLoader: oldClass.
+ "/ ...from reflection cache....
+ JavaVM reflection removeJavaClassObjectForClass: oldClass.
+ "/ ...and from Smalltalk dictionary
+ self unregisterClassInSmalltalk: oldClass notify: true.
]
].
"Created: / 04-04-2012 / 02:43:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 14-09-2013 / 23:41:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified (comment): / 17-10-2013 / 02:25:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 11-08-2014 / 01:57:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
unregisterClassLoader: aJavaClassLoader
--- a/JavaClassReloader.st Mon Aug 11 01:55:40 2014 +0100
+++ b/JavaClassReloader.st Mon Aug 11 09:46:49 2014 +0100
@@ -181,8 +181,11 @@
unload: oldClass
- oldClass subclassesDo:[:cls |
- JavaVM registry unregisterClass: cls
+ oldClass subclassesDo:[:subclass |
+ JavaVM registry unregisterClass: subclass.
+ ].
+ oldClass innerClassesIgnoreUnloaded do:[:innerclass |
+ JavaVM registry unregisterClass: innerclass.
].
JavaVM registry allClassesDo:[:cls|
"/ JV: Q: Should we remove all users of the interface? Let's do it, but not
@@ -191,14 +194,7 @@
ifaces := cls getInterfaces.
ifaces notNil ifTrue:[
- (ifaces anySatisfy:[:ref|
- ref isJavaClass ifTrue:[
- ref == oldClass
- ] ifFalse:[
- ref name = oldClass binaryName
- ]
- ]) ifTrue:[
-
+ (ifaces anySatisfy:[:ref| ref isJavaClass ifTrue:[ ref == oldClass] ifFalse:[ ref name = oldClass binaryName ] ]) ifTrue:[
JavaVM registry unregisterClass: cls
].
].
@@ -206,7 +202,7 @@
]
"Created: / 14-09-2013 / 15:53:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 09-04-2014 / 18:43:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified (format): / 08-08-2014 / 22:38:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaClassReloader methodsFor:'reloading-requests'!
--- a/experiments/JavaClassReloaderTests.st Mon Aug 11 01:55:40 2014 +0100
+++ b/experiments/JavaClassReloaderTests.st Mon Aug 11 09:46:49 2014 +0100
@@ -2172,6 +2172,137 @@
"Created: / 14-09-2013 / 19:04:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 15-09-2013 / 00:40:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_unloading_03a
+ "
+ 1) compile class A with inner class InnerA
+ 2) remove class A
+ 3) check that InnerA has been removed too.
+ "
+
+ | jclassA jclassInnerA |
+
+ self compileAndRegister:'
+public class test_unloading_03a_A {
+ public static class InnerA {
+ }
+}'.
+
+ jclassA := JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader.
+ jclassInnerA := JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA).
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA).
+
+ jclassA removeFromSystem.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA) not.
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA) not.
+
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader) isNil.
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader) isNil.
+
+ "Created: / 08-08-2014 / 22:00:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 08-08-2014 / 23:02:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_unloading_03b
+ "
+ 1) compile class A with inner class InnerA
+ 2) remove class A
+ 3) check that both classes are gone
+ "
+
+ | jclassA jclassInnerA |
+
+ self compileAndRegister:'
+public class test_unloading_03a_A {
+ public static class InnerA {
+ }
+}'.
+
+ jclassA := JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader.
+ jclassInnerA := JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA).
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA).
+
+ jclassInnerA removeFromSystem.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA) .
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA) not.
+
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader) notNil.
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader) isNil.
+
+ "Created: / 11-08-2014 / 09:25:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_unloading_03c
+ "
+ 1) compile class A with inner class InnerA
+ 2) remove class A
+ 3) check that both classes are gone
+ "
+
+ | jclassA jclassInnerA |
+
+ self compileAndRegister:'
+public class test_unloading_03a_A {
+ public static class InnerA {
+ }
+}'.
+
+ jclassA := JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader.
+ jclassInnerA := JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA).
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA).
+
+ jclassA removeFromSystem.
+ jclassInnerA removeFromSystem.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA) not.
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA) not.
+
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader) isNil.
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader) isNil.
+
+ "Created: / 11-08-2014 / 09:25:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_unloading_03d
+ "
+ 1) compile class A with inner class InnerA
+ 2) remove class A
+ 3) check that both classes are gone
+ "
+
+ | jclassA jclassInnerA |
+
+ self compileAndRegister:'
+public class test_unloading_03a_A {
+ public static class InnerA {
+ }
+}'.
+
+ jclassA := JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader.
+ jclassInnerA := JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA).
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA).
+
+ jclassInnerA removeFromSystem.
+ jclassA removeFromSystem.
+
+ self assert: (Smalltalk allClasses includesIdentical: jclassA) not.
+ self assert: (Smalltalk allClasses includesIdentical: jclassInnerA) not.
+
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A' definedBy: testClassLoader) isNil.
+ self assert: (JavaVM classNamed: #'test_unloading_03a_A$InnerA' definedBy: testClassLoader) isNil.
+
+ "Created: / 11-08-2014 / 09:26:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaClassReloaderTests class methodsFor:'documentation'!
--- a/experiments/experiments.rc Mon Aug 11 01:55:40 2014 +0100
+++ b/experiments/experiments.rc Mon Aug 11 09:46:49 2014 +0100
@@ -25,7 +25,7 @@
VALUE "LegalCopyright", "Copyright Claus Gittinger 1988-2014\nCopyright eXept Software AG 1998-2014\0"
VALUE "ProductName", "Smalltalk/X\0"
VALUE "ProductVersion", "6.2.4.0\0"
- VALUE "ProductDate", "Mon, 11 Aug 2014 00:51:54 GMT\0"
+ VALUE "ProductDate", "Mon, 11 Aug 2014 08:34:44 GMT\0"
END
END
--- a/libjava.rc Mon Aug 11 01:55:40 2014 +0100
+++ b/libjava.rc Mon Aug 11 09:46:49 2014 +0100
@@ -25,7 +25,7 @@
VALUE "LegalCopyright", "Copyright Claus Gittinger 1988-2011\nCopyright eXept Software AG 1998-2011\nCopyright Jan Vrany, Jan Kurs and Marcel Hlopko\n SWING Research Group, Czech Technical University In Prague\0"
VALUE "ProductName", "Smalltalk/X\0"
VALUE "ProductVersion", "6.2.4.0\0"
- VALUE "ProductDate", "Mon, 11 Aug 2014 00:51:52 GMT\0"
+ VALUE "ProductDate", "Mon, 11 Aug 2014 08:34:41 GMT\0"
END
END
--- a/tools/tools.rc Mon Aug 11 01:55:40 2014 +0100
+++ b/tools/tools.rc Mon Aug 11 09:46:49 2014 +0100
@@ -25,7 +25,7 @@
VALUE "LegalCopyright", "Copyright Claus Gittinger 1988-2011\nCopyright eXept Software AG 1998-2011\0"
VALUE "ProductName", "Smalltalk/X\0"
VALUE "ProductVersion", "6.2.4.0\0"
- VALUE "ProductDate", "Mon, 11 Aug 2014 00:51:57 GMT\0"
+ VALUE "ProductDate", "Mon, 11 Aug 2014 08:34:47 GMT\0"
END
END