关于Java类加载器是什么,以及如何/*为什么编写您的own...but,这里有1000万篇文章和文档--它们似乎都在假设一些我无法找到简单答案的东西!
我理解类加载器的工作:读取字节码并从它构造一个对象。不同的类加载器会以不同的方式完成这些操作,等等。
但是,我从未在自己的代码中使用类加载器API编写代码,也从未编写过自己的类加载器API,因此,当一个ClassLoader**'s自己的代码真正触发时,我很难理解。
例如:
public static void main(String[] args) {
Fizz fizz = new Fizz();
fuzz.buzz();
}这里,我们有一个Fizz对象。在实例化Fizz之前,我们需要一个类加载器来启动并将Fizz.class加载到它的缓存中。何时何地发生这种情况?!?!它在我的代码中没有显式显示,所以它必须隐式地位于JRE.中的某个地方?
关于这个问题,如果我编写我自己的类加载器,比如说,WidgetClassLoader,并且希望将它配置为加载我的应用程序的所有类,或者仅仅加载我的Fizz.class,我如何将这个WidgetClassLoader“绑定”到我的应用程序中,以便它知道使用哪个类加载器?我的代码是否需要显式调用这个类加载程序,还是像第一个示例那样是隐式的?提前感谢!
发布于 2012-07-18 16:06:39
你的问题并不像你现在想的那么琐碎。
您的Fizz示例: Fizz何时加载?这是在JLS (第5.4章:链接)中定义的。它没有定义何时加载Fizz,但是它保证了可见的行为。对于“when”部分,如果找不到Fizz,将从访问Fizz的第一个语句(Fizz = new ())中抛出异常。我非常肯定它将是新的Fizz(),特别是在本例中,因为表达式的右侧首先被忽略。如果你是这样写的话:
Fizz fizz = null;
fizz = new Fizz();在本例中,Fizz = null已经抛出异常,因为它是对fizz类的第一次访问。
谁来装Fizz?当必须加载类时,“属于”需要该类的代码的类加载器将用于获取类。在Fizz示例中,这将是用main方法加载类的类加载器。当然,如果类加载器本身不能加载Fizz,则可以选择委托给其父类加载器。
如何让JVM使用我的ClassLoader?有两种方式,显式或隐式。显式:通过调用类的方法,可以通过自己的类加载器加载类。笨拙:当您从已从类加载器加载的类执行代码(意为方法或初始化器)时,需要在过程中解析类引用,因为首先加载代码的是类加载程序,因此类加载器将自动使用。
发布于 2012-07-18 15:46:56
Java有一个默认的类加载器。这将在默认类路径中查找类声明。如果您编写了自己的类加载器,您可以(并且应该)设置父类加载器。如果您没有其他的,这将是默认的。如果yuo不这样做,那么类加载器就无法找到java类。如果java查找一个类,它不会开始使用自定义类加载器,而是使用父类加载器。如果这个有父母,它就从那里开始,依此类推。只有在找不到类时,才会使用下一个子类加载程序再试一次。同样,只要有儿童,这种情况就会继续下去。如果链中的任何加载程序找不到该类,则会引发ClassNotFoundException。
当然,只有在先将类加载器设置为默认类加载器(通过调用Thread.currentThread().setContextClassLoader())或手动加载类(通过调用loadClass())时,java才会使用该类加载器。
我不确定什么时候调用类加载器。我认为它是在启动程序(在所有声明为import的类上)或首次使用类(变量声明或构造函数调用)时调用的。
发布于 2012-07-18 16:17:04
类的实际创建发生在defineClass中。类是使用来自多个源中任何一个的字节数组创建的。
到达defineClass (也就是protected)的正常路径是通过findClass (当然,也是protected)。通常的入口点是loadClass -> findClass -> defineClass。但对于特殊情况,还有其他的途径。
(整个过程非常复杂,代表了随着保护变得更加复杂和访问方式更加多样化而增加层的历史。)
https://stackoverflow.com/questions/11545067
复制相似问题