-
Bug
-
Resolution: Not an Issue
-
P3
-
None
-
1.1.8
-
generic
-
generic
THIS BUG REPORT IS FILED FOR SUBMISSION OF AN ESCALATION TO CTE.
The customer has written a custom class loader which generates VerifyErrors at
resolve time. The custom class loader is designed along the lines of the
example presented by Sheng Liang and Gilad Bracha in their paper "Dynamic Class
Loading in the Java Virtual Machine", and the code appears to be correct.
No transformation is performed upon the classes loaded by the custom loader, and
the classes are loaded without error by the primordial loader.
The problem appears on both Solaris and win32, on 1.1.8 as well as 1.2. It appears when the code is compiled with any compiler version, and whether the
JIT is turned on or off. When run with 1.2, the VerifyError appears as follows:
java.lang.VerifyError: (class: com/ensemble/coordinator/CoordinatedObject, method: printCoordinationMode signature: (Lcom/ensemble/coordinator/utilities/DisplayStream;)V) Incompatible type for getting or setting field
The error message can be traced to line 1992 of src/share/native/common/check_code.c in the 1.2 JVM source.
Here is the code for the customer's class loader:
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = null;
if(isSystemClassName(name)) {
trace("<- <system> "+name);
return findSystemClass(name);
}
BasicClassDescriptor cd = BasicClassDescriptor.lookup(name);
// transform the bytes if the class is coordinated
if(cd.isCoordinated()) {
ClassFile cf = cd.getFile();
cf.augmentInline();
return install(cf, resolve);
} else {
c = findSystemClass(name);
cd.setDescribedClass(c);
return c;
}
}
public Class install(ClassFile cf, boolean resolve)
throws ClassNotFoundException
{
Class installedClass = null;
String className = cf.classDescriptor.className;
try {
byte data[] = cf.getData();
installedClass = defineClass(className, data, 0, data.length);
cf.classDescriptor.setDescribedClass(installedClass);
if(resolve) {
resolveClass(installedClass);
}
} catch (Throwable e) {
cf.verify();
// write myself for diagnosis
trace("INSTALL FAILED! "+className+", dumping to file");
try {
cf.write();
} catch(IOException e2) {
e2.printStackTrace();
}
WarningDialog.panic("class generator error: "+className, e);
}
return installedClass;
}
The customer's application is highly complex, and the customer has been unable
to extract a workable test case. The customer's application can be found in
the file /home/nrodin/cases/adaptec/716368/coordinator.tar. Packaged with the
application are compile2.bat and run.bat for compiling and running the program
on win32. These files will need to be modified to execute in your environment.
Attached are ClassManager.java, which contains the above source, and test_output, a screen dump from running the application. Line 27 of test_output
shows the class CoordinatedObject being loaded by the primordial loader (line 154 of ClassManager.java). On line 102, a VerifyError occurs when the same class is loaded by the custom class loader.
The customer has written a custom class loader which generates VerifyErrors at
resolve time. The custom class loader is designed along the lines of the
example presented by Sheng Liang and Gilad Bracha in their paper "Dynamic Class
Loading in the Java Virtual Machine", and the code appears to be correct.
No transformation is performed upon the classes loaded by the custom loader, and
the classes are loaded without error by the primordial loader.
The problem appears on both Solaris and win32, on 1.1.8 as well as 1.2. It appears when the code is compiled with any compiler version, and whether the
JIT is turned on or off. When run with 1.2, the VerifyError appears as follows:
java.lang.VerifyError: (class: com/ensemble/coordinator/CoordinatedObject, method: printCoordinationMode signature: (Lcom/ensemble/coordinator/utilities/DisplayStream;)V) Incompatible type for getting or setting field
The error message can be traced to line 1992 of src/share/native/common/check_code.c in the 1.2 JVM source.
Here is the code for the customer's class loader:
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = null;
if(isSystemClassName(name)) {
trace("<- <system> "+name);
return findSystemClass(name);
}
BasicClassDescriptor cd = BasicClassDescriptor.lookup(name);
// transform the bytes if the class is coordinated
if(cd.isCoordinated()) {
ClassFile cf = cd.getFile();
cf.augmentInline();
return install(cf, resolve);
} else {
c = findSystemClass(name);
cd.setDescribedClass(c);
return c;
}
}
public Class install(ClassFile cf, boolean resolve)
throws ClassNotFoundException
{
Class installedClass = null;
String className = cf.classDescriptor.className;
try {
byte data[] = cf.getData();
installedClass = defineClass(className, data, 0, data.length);
cf.classDescriptor.setDescribedClass(installedClass);
if(resolve) {
resolveClass(installedClass);
}
} catch (Throwable e) {
cf.verify();
// write myself for diagnosis
trace("INSTALL FAILED! "+className+", dumping to file");
try {
cf.write();
} catch(IOException e2) {
e2.printStackTrace();
}
WarningDialog.panic("class generator error: "+className, e);
}
return installedClass;
}
The customer's application is highly complex, and the customer has been unable
to extract a workable test case. The customer's application can be found in
the file /home/nrodin/cases/adaptec/716368/coordinator.tar. Packaged with the
application are compile2.bat and run.bat for compiling and running the program
on win32. These files will need to be modified to execute in your environment.
Attached are ClassManager.java, which contains the above source, and test_output, a screen dump from running the application. Line 27 of test_output
shows the class CoordinatedObject being loaded by the primordial loader (line 154 of ClassManager.java). On line 102, a VerifyError occurs when the same class is loaded by the custom class loader.