Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Minor
-
Resolution: Fixed
-
Affects Version/s: 2.9.3
-
Fix Version/s: 3.0
-
Component/s: None
-
Labels:None
-
Environment:prototype Jikes RVM 2.9.3+svn (r14214) using GNU Classpath 0.97.1
-
Testcase included:yes
Description
In VM_Annotation there seems to be at least one bug (although I suspect there might be two of them).
In line 297 of said file Jikes uses Class.forName to load the annotation's class file:
value = Class.forName(VM_Class.getUtf(constantPool, classInfoIndex).toString());
But using the single-argument Class.forName(String) causes the bootstrap classloader to be used (as VM_Annotation has been loaded by it). This leads to the following exception, when running the attached test case which the org.junit.runner.JUnitCore runner. To fix this, the three-argument version of Class.forName needs to be used, with this.classLoader as its third argument.
JUnit version 4.3.1
.E
Time: 0.02
There was 1 failure:
1) initializationError0(BugReport)
java.lang.Error: java.lang.ClassNotFoundException: org.junit.Test$Non
at .<invisible method>(Unknown Source:0)
at java.lang.VMThrowable.fillInStackTrace(VMThrowable.java:49)
at java.lang.Throwable.fillInStackTrace(Throwable.java:498)
at java.lang.Throwable.<init>(Throwable.java:159)
at java.lang.Throwable.<init>(Throwable.java:174)
at java.lang.Throwable.<init>(Throwable.java:188)
at java.lang.Error.<init>(Error.java:105)
at org.jikesrvm.classloader.VM_Method.readMethod(VM_Method.java:204)
at org.jikesrvm.classloader.VM_Class.readClass(VM_Class.java:1442)
at org.jikesrvm.classloader.VM_ClassLoader.defineClassInternal(VM_ClassLoader.java:336)
at org.jikesrvm.classloader.VM_ClassLoader.defineClassInternal(VM_ClassLoader.java:307)
at java.lang.VMClassLoader.defineClass(VMClassLoader.java:93)
at java.lang.VMClassLoader.defineClassWithTransformers(VMClassLoader.java:312)
at java.lang.ClassLoader.defineClass(ClassLoader.java:471)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:83)
at java.net.URLClassLoader.findClass(URLClassLoader.java:617)
at java.lang.ClassLoader.loadClass(ClassLoader.java:341)
at java.lang.ClassLoader.loadClass(ClassLoader.java:293)
at org.jikesrvm.classloader.VM_TypeReference.resolveInternal(VM_TypeReference.java:762)
at org.jikesrvm.classloader.VM_TypeReference.resolve(VM_TypeReference.java:750)
at org.jikesrvm.classloader.VM_Class.getLiteralOffset(VM_Class.java:700)
at org.jikesrvm.classloader.VM_Class.getLiteralOffset(VM_Class.java:679)
at org.jikesrvm.compilers.baseline.VM_CompilerFramework.genCode(VM_CompilerFramework.java:345)
at org.jikesrvm.compilers.baseline.VM_BaselineCompiler.compile(VM_BaselineCompiler.java:255)
at org.jikesrvm.compilers.baseline.VM_BaselineCompiledMethod.compile(VM_BaselineCompiledMethod.java:145)
at org.jikesrvm.compilers.baseline.VM_BaselineCompiler.compile(VM_BaselineCompiler.java:177)
at org.jikesrvm.compilers.common.VM_RuntimeCompiler.baselineCompile(VM_RuntimeCompiler.java:293)
at org.jikesrvm.compilers.common.VM_RuntimeCompiler.compile(VM_RuntimeCompiler.java:754)
at org.jikesrvm.classloader.VM_NormalMethod.genCode(VM_NormalMethod.java:175)
at org.jikesrvm.classloader.VM_Method.compile(VM_Method.java:695)
at org.jikesrvm.runtime.VM_DynamicLinker$DL_Helper.compileMethod(VM_DynamicLinker.java:149)
at org.jikesrvm.runtime.VM_DynamicLinker.lazyMethodInvoker(VM_DynamicLinker.java:45)
at org.junit.internal.runners.TestClassRunner.<init>(TestClassRunner.java:20)
at .<invisible method>(Unknown Source:0)
at org.jikesrvm.runtime.VM_Reflection.invoke(VM_Reflection.java:132)
at org.jikesrvm.runtime.VM_Reflection.invoke(VM_Reflection.java:45)
at java.lang.reflect.VMConstructor.construct(VMConstructor.java:121)
at java.lang.reflect.Constructor.newInstance(Constructor.java:318)
at org.junit.internal.requests.ClassRequest.buildRunner(ClassRequest.java:33)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:28)
at org.junit.internal.requests.ClassesRequest.getRunner(ClassesRequest.java:21)
at org.junit.runner.JUnitCore.run(JUnitCore.java:109)
at org.junit.runner.JUnitCore.run(JUnitCore.java:100)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:81)
at org.junit.runner.JUnitCore.main(JUnitCore.java:44)
Caused by: java.lang.ClassNotFoundException: org.junit.Test$Non
at .<invisible method>(Unknown Source:0)
at java.lang.VMThrowable.fillInStackTrace(VMThrowable.java:49)
at java.lang.Throwable.fillInStackTrace(Throwable.java:498)
at java.lang.Throwable.<init>(Throwable.java:159)
at java.lang.Exception.<init>(Exception.java:78)
at java.lang.ClassNotFoundException.<init>(ClassNotFoundException.java:84)
at org.jikesrvm.classloader.VM_BootstrapClassLoader.findClass(VM_BootstrapClassLoader.java:183)
at org.jikesrvm.classloader.VM_BootstrapClassLoader.loadClass(VM_BootstrapClassLoader.java:145)
at java.lang.ClassLoader.loadClass(ClassLoader.java:293)
at org.jikesrvm.classloader.VM_TypeReference.resolveInternal(VM_TypeReference.java:762)
at org.jikesrvm.classloader.VM_TypeReference.resolve(VM_TypeReference.java:750)
at java.lang.Class.forNameInternal(Class.java:678)
at java.lang.Class.forName(Class.java:95)
at org.jikesrvm.classloader.VM_Annotation.readValue(VM_Annotation.java:297)
at org.jikesrvm.classloader.VM_Annotation.readValue(VM_Annotation.java:221)
at org.jikesrvm.classloader.VM_Method.readMethod(VM_Method.java:202)
...37 more
FAILURES!!!
Tests run: 1, Failures: 1
The second bug I have alluded to above manifest itself in the fact that the class Jikes attempts to load is org.junit.Test$Non; however, it ought to be org.junit.Test$None (note the trailing 'e'). Somehow, the last character gets eaten, most likely due to confusion whether Jikes has to deal with a type descriptor or an internal class name here.
Issue Links
- relates to
-
RVM-333
Annotations used for VM Pragmas (NoInline, Uninterruptible, etc) probably should not be as closed linked to classloaders
-
Just to confirm the problem with the class loader, I believe a similar problem for enums has been fixed. I can't reproduce the lost 'e' problem, could you give a test case not reliant on me having to do too muck work with junit? There's another problem if a value that annotates a class is a class literal of that class then we either recurse or die with a class not found. Ie:
@interface testAnnotation {
Class value;
}
@testAnnotation{test.class}
class test {}
We can't possibly create the test.class value as the class hasn't yet been loaded. We need some way to defer this case.