因此,每本Java教科书都讨论了Java的灵活性,因为它可以在运行时加载类.只需拼凑一个字符串并将其交给它Class.forName(),然后抓住ClassNotFoundException并处理它.这个理论太多了.
您能举例说明您是如何使用Java类加载来实现一个本来不可能或不容易的功能的吗?请注意,我不是问"有什么伟大的事情可以做什么?" - 我正在寻找真实世界的例子,无论是开源应用程序还是 - 如果你能够在不提供太多细节的情况下描述它 - 一个专有的应用程序.
编辑:当然,VM会根据需要懒惰地加载类.只要我确信我所需要的所有课程都在那里,这就是幕后的事情.我该怎么处理ClassNotFoundException?假设我写了十页文本,并且PrinterDriver找不到该课程.
Tomcat 类加载器HOW-TO文档描述了4种不同的类加载器:
但是,在默认的catalina.properties文件中,还为共享和服务器类加载器定义了属性.在文件的默认版本中,这两个属性都是空的,注释说:
如果保留为空白,则"common"加载程序将用作Catalina的"共享"/"服务器"加载程序.
我无法找到有关这些类加载器的任何其他文档.我的问题是,共享和系统加载器相对于公共加载器的搜索顺序是什么?此外,这些类加载器的用途是什么?
最近,当我java.lang.IllegalAccessError尝试从内部类访问由不同类加载器加载的外部父类中声明的受保护字段时,我遇到了运行时错误的问题。简要地:
Parent有受保护的字段p。Outer扩展Parent。Inner是在 class 中定义的内部类Outer。Inner类里面有一个代码:Outer.this.p.通常它的编译和运行正常,直到Parent和Outer类是由不同的类加载器加载。在这种情况下,我们java.lang.IllegalAccessError在尝试Outer.this.p从Inner. 我发现了一个旧的错误报告(这似乎是一个功能)描述了这种行为:
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6258289
但分辨率对我来说听起来自相矛盾:
关键是在失败的情况下,内部类不在同一个包中(并且不是 ConcreteCommand/AbstractCommand 的子类)。这只是违反了受保护类的 Java 规范。
听起来是对的。但是,如果我们在不同的包中声明Parent和Outer类,但使用单个类加载器加载(只需创建没有任何 jar 加载的示例控制台应用程序),我们就不会收到任何错误。因此,从技术上讲,它违反了受保护类的 Java 规范,但由于我们使用了内部类,因此它可以工作。
因此,对于“不同的包”的两种情况,我们有不同的行为。
有人可以清楚地解释内部类如何访问父类的字段以及为什么它在两种情况下的工作方式不同吗?
我已经为此阅读了很多equinox代码,但仍然无法弄清楚在eclipse equinox设置中获取osgi包的类加载器的非hacky方法.有吗?
如何从类加载器中卸载一个类,以便我可以动态使用最近更改的类而无需重新启动我的应用程序(热部署)?有可能吗?
如何在运行时将JDBC驱动程序添加到Jython?使用CLASSPATH工作,但使用sys.path不能与zxJDBC一起使用,即使该类导入正常并且可以从Jython解释器提示符进行操作.
为什么这样做:
$ CLASSPATH=/tmp/jtds\-1.2.5.jar ./jython
*sys-package-mgr*: processing new jar, '/private/tmp/jtds-1.2.5.jar'
Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54)
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20
Type "help", "copyright", "credits" or "license" for more information.
>>> from java.lang import Class
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver')
<type 'net.sourceforge.jtds.jdbc.Driver'>
Run Code Online (Sandbox Code Playgroud)
但这不是吗?
$ ./jython
Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54)
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path.extend(['/tmp/jtds-1.2.5.jar'])
>>> from java.lang …Run Code Online (Sandbox Code Playgroud) 我看到一些类加载行为似乎与JVM规范不一致,我想知道这是否是一个错误.或者如果没有,希望有人可以解释原因.
下面的示例代码只是从其main方法打印hello.它有一个未使用的方法,它包含对方法的方法调用,该方法声明它将'C'(作为接口)作为参数.
当执行main时(类路径中没有A,B和C),接口C将抛出ClassNotFound错误.(因为它仅在永不执行的方法中引用,因此在运行时实际上不需要注释C).
这似乎违反了JVM规范
Java VM Spec的第2.17.1节第2版说:
关于何时执行解析的唯一要求是,在解析期间检测到的任何错误都必须抛到程序中的某个点,程序可能会直接或间接地需要链接到错误中涉及的类或接口.
Java VM Spec的第2.17.3节第2版说:
Java编程语言允许实现灵活性,以便何时发生链接活动(并且,由于递归,加载),只要语言的语义得到尊重,类或接口在初始化之前完全验证和准备,并且在链接期间检测到的错误被抛出到程序中的某个点,在该点上程序可能需要链接到错误中涉及的类或接口.
注意:如果我将定义中的参数类型更改为类而不是接口,则代码会正确加载和执行.
/**
* This version fails, the method call in neverCalled() is to a method whose
* parameter definition is for an Interface
*/
public class Main {
public void neverCalled(){
A a = new A();
B b = new B(); // B implements C
//method takeInter is declared to take paramters of type Interface C
//This code is causes a ClassNotFound error …Run Code Online (Sandbox Code Playgroud) 最近我遇到了java自定义类加载器api.我在这里发现了一个用途,kamranzafar的博客 我对类加载器概念有点新意.任何人都可以详细解释,我们可能需要它或我们应该使用它的不同场景是什么?
假设我有一个项目K.
K取决于lib.jar
在lib.jar,有一个名为的类x.y.z.Foo
如果我x.y.z.Foo在K中创建相同的类,那么在我创建实例的这个项目中Foo,现在将JVM用Foo在K而不是lib.jar?
如果它不稳定或取决于某些东西,如何确保Foo应该使用K的版本而不是lib.jar?
在Android 5.0之前,我能够使用DexClassLoader和调用loadClass()方法动态加载DEX文件,但是使用最新的Android版本,我得到了一个ClassNotFoundException.
这是我在做的事情:
生成DEX文件.
../android-sdk/android-sdk-linux_86/build-tools/21.1.1/dx --dex --output=bin/output.dex bin/output.jar
Run Code Online (Sandbox Code Playgroud)创建一个DexClassLoader.
DexClassLoader cl = new DexClassLoader(
dexFile.getAbsolutePath(),
odexFile.getAbsolutePath(),
null,
mContext.getClassLoader());
Run Code Online (Sandbox Code Playgroud)呼叫 cl.loadClass("myMethod");
我知道ART使用dex2oat来生成一个由ART加载的ELF文件但是在步骤2中我生成了一个ODEX文件,因此我不需要在ART中运行以在运行时加载DEX文件,任何人都可以帮助我 ?