-
Bug
-
Resolution: Fixed
-
P3
-
1.1
-
1.2beta4
-
sparc
-
solaris_2.5
-
Not verified
Name: szC45993 Date: 03/21/97
In certain cases JDK1.1's VM uses ClassLoader differently comparing with JDK1.0.2
and JVM and API specification books.
Particularly,
(1) VM makes class resolving not through "loadClass" method with resolve=true argument;
(2) VM resolves superclasses not through "loadClass" method with resolve=true argument;
More details:
(1)
The Java API, Volume 1, Core Packages, 1.4 Class ClassLoader says:
"The methods and constructors of objects created by a class
loader may reference other classes. To determine the class(es)
referred to, the Java Virtual Machine calls the loadClass
method (I-1.4.4) of the class loader that originally created
the class. If the Java Virtual Machine only needs to determine
if the class exists to know its superclass, the resolve flag is
set to false. However, if an instance of the class is being
created or any of its methods are being called, the class must
also be resolved. In this case the resolve flag is set to true
(for loadClass), and the resolveClass method (I-1.4.5) should
be called.".
Test below loads class "Intrmdt" using "myClassLoader.loadClass()"
method with resolve flag is set to false. Then instance of the "Intrmdt"
class is created using newInstance() which causes JVM to resolve the "Intrmdt"
class. Note, that JVM spec doesn't specify explicitlty JVM behaviour in this
case: is this resolving legal or illegal? In any case it is done not through
the myClassLoader.loadClass().
(2)
The JVM Specification [5.1.2 Current Class or Interface Loaded by a Class Loader,
p.145-146], says:
"Linking and initializing a class or interface created by a
class loader is very similar to linking and initializing a
class or interface without a class loader (steps 2-4 of 5.1.1):
First, the superclass of the class or interface is linked and
initialized by calling the loadClass method of the class loader
with the fully qualified name of the superclass as the first
argument, and true as the second argument. Linking and
initialization may result in the superclass's own superclass
being linked and initialized."
Again as in the first case JDK1.1's JVM makes resolving of "clss" directly
and doesn't call "myClassLoader.loadClass()" at all.
novo7% java -version
java version "JDK1.1.1C"
novo7% java -verify javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.ClassInterf03601
********ClassInterf03601.run*********
Begin loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.Intrmdt false
Begin loadClassData: Intrmdt
End loadClassData: Intrmdt
Begin defineClass: Intrmdt
Begin loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.clss false
Begin loadClassData: clss
End loadClassData: clss
Begin defineClass: clss
Begin loadClass: java.lang.Object false
Begin findSystemClass: java.lang.Object
End findSystemClass: java.lang.Object
End loadClass: java.lang.Object false
End defineClass: clss
End loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.clss false
End defineClass: Intrmdt
End loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.Intrmdt false
Begin loadClass: java.lang.System false
Begin findSystemClass: java.lang.System
End findSystemClass: java.lang.System
End loadClass: java.lang.System false
Begin loadClass: java.io.PrintStream false
Begin findSystemClass: java.io.PrintStream
End findSystemClass: java.io.PrintStream
End loadClass: java.io.PrintStream false
clss INITIALIZING begin
clss INITIALIZING end
Begin loadClass: java.lang.Runnable false
Begin findSystemClass: java.lang.Runnable
End findSystemClass: java.lang.Runnable
End loadClass: java.lang.Runnable false
Intrmdt INITIALIZING begin
Begin loadClass: java.lang.String false
Begin findSystemClass: java.lang.String
End findSystemClass: java.lang.String
End loadClass: java.lang.String false
Intrmdt INITIALIZING end
********Intrmdt.run*********
********clss.prc*********
novo7% java -version
java version "1.0.2"
novo7% java -verify javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.ClassInterf03601
********ClassInterf03601.run*********
Begin loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.Intrmdt false
Begin loadClassData: Intrmdt
End loadClassData: Intrmdt
Begin defineClass: Intrmdt
Begin loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.clss false
Begin loadClassData: clss
End loadClassData: clss
Begin defineClass: clss
Begin loadClass: java.lang.Object false
Begin findSystemClass: java.lang.Object
End findSystemClass: java.lang.Object
End loadClass: java.lang.Object false
End defineClass: clss
End loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.clss false
End defineClass: Intrmdt
End loadClass: javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.Intrmdt false
java.lang.NoSuchMethodError
at javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.ClassInterf03601.run(ClassInterf03601.java:128)
at javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.ClassInterf03601.main(ClassInterf03601.java:146)
-----------------------------------------------------------------------
--------------------- ClassInterf03601.java
package javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601;
import java.io.PrintStream;
import java.io.*;
import java.lang.*;
import java.util.*;
class myClassLoader extends java.lang.ClassLoader {
Hashtable cache = new Hashtable();
private byte loadClassData(String name)[] {
String pckg = "/javasoft/sqe/tests/vm/constantpool/_tmp/ClassInterf03601/";
String str_1;
String str_2;
String str1 = "";
String str2 = ""+pckg;
byte bt[];
int length;
int index = 0;
Properties prpr = System.getProperties();
System.out.println("Begin \t loadClassData: \t"+name);
str_1 = prpr.getProperty("java.class.path");
str2 = str2.concat(name);
str2 = str2.concat(".class");
str1 = str1.concat(str_1.substring(str_1.indexOf(":")+1));
try{
index = str_1.indexOf(":");
str_1 = str_1.substring(0,index);
} catch (Exception e) {System.out.println(e);return null;};
str_2 = str_1.concat(pckg+"Intrmdt.class");
str_1 = str_1.concat(str2);
while (true) {
File fl1;
fl1 = new File(str_2);
if (fl1.isFile()) {
break;
} else {
str_1 = "";
try{
index = str1.indexOf(":");
str_1 = str_1.concat(str1.substring(0,index));
} catch (Exception e) {System.out.println(e);return null;};
str1 = str1.substring(str1.indexOf(":")+1);
str_2 = str_1.concat(pckg+"Intrmdt.class");
str_1 = str_1.concat(str2);
}
}
try{
FileInputStream fl3;
fl3 = new FileInputStream(str_1);
length = fl3.available();
bt = new byte[length];
fl3.read(bt);
fl3.close();
} catch (java.io.IOException e) {System.out.println(e);return null;};
System.out.println("End \t loadClassData: \t"+name);
return bt;
}
public synchronized Class loadClass(String name, boolean resolve) {
Class c = (Class) cache.get(name);
String s1 = "Intrmdt";
String s2 = "clss";
String s3 = "ClassInterf03601";
String s4 = "Runnable";
String name1;
System.out.println("Begin \t loadClass: \t"+name+" "+resolve);
if (name.indexOf(s1) != -1) {
name1 = s1;
} else if (name.indexOf(s2) != -1) {
name1 = s2;
} else {
name1 = name;
}
if (name1.indexOf(".") != -1) {
if (c == null) {
try{
System.out.println("Begin \t findSystemClass: \t"+name);
c = findSystemClass(name1);
System.out.println("End \t findSystemClass: \t"+name);
}
catch (java.lang.ClassNotFoundException e) {
System.out.println(e);
return null;
};
cache.put(name, c);
}
} else {
if (c == null) {
byte data[] = loadClassData(name1);
System.out.println("Begin \t defineClass: \t"+name1);
c = defineClass(data,0,data.length);
System.out.println("End \t defineClass: \t"+name1);
cache.put(name, c);
}
}
if (resolve) {
System.out.println("Begin \t resolveClass: \t"+c);
resolveClass(c);
System.out.println("End \t resolveClass: \t"+c);
}
System.out.println("End \t loadClass: \t"+name+" "+resolve);
return c;
}
}
public class ClassInterf03601 {
public static int run(String argv[], PrintStream out) {
myClassLoader mcl = new myClassLoader();
Object obj = null;
try{
out.println("********ClassInterf03601.run*********");
obj = mcl.loadClass( "javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601.Intrmdt", false).newInstance();
}
catch (java.lang.IllegalAccessException e) {
out.println(e);
return 0;
}
catch (java.lang.InstantiationException e) {
out.println(e);
return 0;
};
((Runnable) obj).run();
return 2;
}
public static void main(String argv[]) {
System.exit(run(argv, System.out) + 95/*STATUS_TEMP*/);
}
}
--------------------- Intrmdt.java
package javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601;
import java.io.PrintStream;
import java.lang.*;
public class Intrmdt extends clss implements Runnable{
static String str = "Class Intrmdt is linked";
static {
System.out.println(" Intrmdt INITIALIZING begin");
str = str.concat(clss.str);
System.out.println(" Intrmdt INITIALIZING end");
}
public void run() {
System.out.println("********Intrmdt.run*********");
super.run();
}
}
--------------------- clss.java
package javasoft.sqe.tests.vm.constantpool._tmp.ClassInterf03601;
import java.io.PrintStream;
import java.io.*;
import java.lang.*;
public class clss{
static String str;
static {
System.out.println(" clss INITIALIZING begin");
str = " and initialized!";
System.out.println(" clss INITIALIZING end");
}
public void run() {
System.out.println("********clss.prc*********");
}
}
-----------------------------------------------------------------------
======================================================================