我做了一个新的
ClassLoader
Class
Class.getPackage
getPackage
在我的主命名空间中的任何其他类上。
根据
JVM spec
:
接口由包决定
类加载器的名称和定义
类或接口。
换句话说,如果在同一个包中有两个类,但是由不同的类加载器加载,那么它们被认为在不同的包中(这也可以通过下面我的测试用例中的反射来“确认”。)
所以当我这么做的时候,我得到的结果是一样的
获取包
在两个班上?
package pkg;
import java.io.*;
// Yes, you can try commenting this class, you'll get the same result.
class LoadedClass {
LoadedClass() {
System.out.println("LoadedClass init");
}
}
class MyClassLoader extends ClassLoader {
Class<?> defineClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}
class Main {
public static void main(String[] args) throws Exception {
MyClassLoader mcl = new MyClassLoader();
// load compiled class from file
FileInputStream fileinputstream = new FileInputStream(
"/home/me/test/pkg/LoadedClass.class" /* <- point to whever these classes
* are being compiled to. */
);
int numberBytes = fileinputstream.available();
byte classBytes[] = new byte[numberBytes];
fileinputstream.read(classBytes);
fileinputstream.close();
Class<?> lc = mcl.defineClass("pkg.LoadedClass", classBytes);
Package myPackage = Main.class.getPackage();
Package lcPackage = lc.getPackage();
System.out.println("lc package: " + lcPackage);
System.out.println("my package: " + myPackage);
System.out.println("lc ClassLoader: " + lc.getClassLoader());
System.out.println("lc ClassLoader parent: " +
lc.getClassLoader().getParent());
System.out.println("my ClassLoader: " + Main.class.getClassLoader());
System.out.println("are they equal? " + (lcPackage == myPackage));
if (lcPackage == myPackage) {
System.out.println("okay... we should be able to instantiate " +
"the package if that's true, lets try");
lc.newInstance(); // boom as expected
}
}
}
它输出:
lc package: package pkg
my package: package pkg
lc ClassLoader: pkg.MyClassLoader@7987aeca
lc ClassLoader parent: sun.misc.Launcher$AppClassLoader@1f7182c1
my ClassLoader: sun.misc.Launcher$AppClassLoader@1f7182c1
are they equal? true
okay... we should be able to instantiate the package if that's true, lets try
Exception in thread "main" java.lang.IllegalAccessException: Class pkg.Main can not access a member of class pkg.LoadedClass with modifiers ""
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.Class.newInstance0(Class.java:349)
at java.lang.Class.newInstance(Class.java:308)
at pkg.Main.main(Main.java:42)
不同的
包(相同的名称,不同的命名空间),这是正确的AFAIK,因为它强制类型安全。
我只是想知道,因为我在过去几天一直在研究JVM和安全体系结构,并不断发现像这样的细微之处,所以很难推理。