有人能给我一个很好的资源或者解释一下Class Loaders背后的概念吗?我在类加载器上找到了以下资源http://www.onjava.com/lpt/a/5586但仍然没有帮助.以下问题可能看起来很愚蠢,但试图回答它们总是让我感到困惑.
为什么有这么多种类的装载机?例如:Bootsrap,Comman,Catalina类装载机等,
提前致谢.
我怎样才能做到这一点:
class Foo {
public static Foo get() throws Exception {
ClassLoader cl = new URLClassLoader(new URL[]{"foo.jar"}, null); // Foo.class is in foo.jar
return (Foo)cl.loadClass("Foo").newInstance(); // fails on class cast
}
}
Run Code Online (Sandbox Code Playgroud)
我需要的是让JVM从cl中考虑Foo实例,就好像它是来自执行代码的类加载器的Foo实例一样.
我见过这些方法,对我来说都没有好处(上面的例子是玩具示例):
最近我在接受采访时询问了加载类时调用类加载器的顺序.
不幸的是,我从来没有必要编写自己的类加载器,因此当时不熟悉类加载的复杂性.
这让我想知道,他们编写自己的类加载器的原因是什么.
所以这就是我的问题:人们面临哪些场景需要编写自己的类加载器?
如果我在运行时有一个Class实例,我可以得到它的byte []表示吗?我感兴趣的字节是Class文件格式,这样它们就是[ClassLoader.defineClass] [3]的有效输入.
[3]:http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html#defineClass(java.lang.String ,byb [],int,int)
编辑:我已经接受了一个getResourceAsStream答案,因为它非常简单,大部分时间都可以工作.ClassFileTransformer似乎是一个更强大的解决方案,因为它不需要从.class文件加载类; 例如,它将处理网络加载的类.用这种方法可以通过几个环节跳过,但我会牢记在心.谢谢大家!
我目前正在尝试在Java应用程序中实现热类重新加载,但是有很多插件可供选择,我找不到这些选项之间的良好比较.此外,插件的网站并不十分清楚具体功能是什么以及如何使用它们.
还有一个选项可以让一个自定义的热门类重新加载ClassLoader,但我觉得这类似于"重新发明轮子",如果已经有这么多的插件可以完成这项工作..其他人是否同意这一点?
我找到的Java插件我认为可以完成这项工作:
那么有谁碰巧知道插件之间的差异是什么?还有哪个插件最直观易用?
作为旁注:我实际想要做的是重新加载我的java应用程序的.jar文件依赖项.我有一些java代码经常自动重新编译,然后转换为.jar文件.它是我的java应用程序的依赖项,我的应用程序需要每次都使用此.jar文件的最新版本.
如果已将整个.class文件序列化为byte [],并假设类的名称已知(与byte []一起传递),如何转换byte [] - > Class - >然后将其加载到JVM以便我以后可以通过调用Class.forName()来使用它?
注意: 我这样做是因为我将.class发送到另一台主机,并且主机的JVM不知道这个.class.
这是我的示例抽象单例类:
public abstract class A {
protected static A instance;
public static A getInstance() {
return instance;
}
//...rest of my abstract methods...
}
Run Code Online (Sandbox Code Playgroud)
以下是具体实施:
public class B extends A {
private B() { }
static {
instance = new B();
}
//...implementations of my abstract methods...
}
Run Code Online (Sandbox Code Playgroud)
不幸的是我无法在B类中获取静态代码来执行,因此实例变量永远不会被设置.我试过这个:
Class c = B.class;
A.getInstance() - returns null;
Run Code Online (Sandbox Code Playgroud)
还有这个
ClassLoader.getSystemClassLoader().loadClass("B");
A.getInstance() - return null;
Run Code Online (Sandbox Code Playgroud)
在eclipse调试器中运行这两个,静态代码永远不会被执行.我可以找到执行静态代码的唯一方法是将B的构造函数的可访问性更改为public,并调用它.
我在Ubuntu 32bit上使用sun-java6-jre来运行这些测试.
以下是2个代码段
第一个使用ClassLoader类来加载指定的类
ClassLoader cls = ClassLoader.getSystemClassLoader();
Class someClass = cls.loadClass("TargetClass");
第二个使用Class.forName()来加载指定的类
Class cls = Class.forName("TargetClass");
上述方法之间有什么区别.哪一个用于哪个目的?
我知道有一套令人难以置信的工具可以在java中加载插件类,但今天我想到了一个想法.
如果我在包"org.home.junk"中有一堆带注释和未注释的类(注释带有注释"@AnnotatedClass"),并且那些类具有带注释"@AnnotatedMethod"的注释方法,该怎么办?
第一个问题:我可以在运行时获取该特定包中所有类的数组/集合,以便我可以检查哪个类被注释并创建它们的实例.(我知道如何检查Some.class是否有本指南的注释:http://isagoksu.com/2009/development/java/creating-custom-annotations-and-making-use-of-them/ )
第二个问题: - 如果我能在第一个问题上做我想做的事 - 那么最政治的方式是什么?
我相信这是可能的,因为我理解JUnit以类似的方式加载测试用例类.
如果这可以用最少的第三方库来完成也是很酷的,再次 - 如果可能的话:)
我正在将项目迁移到Kotlin,这个:
public static Properties provideProperties(String propertiesFileName) {
Properties properties = new Properties();
InputStream inputStream = null;
try {
inputStream = ObjectFactory.class.getClassLoader().getResourceAsStream(propertiesFileName);
properties.load(inputStream);
return properties;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
就是现在:
fun provideProperties(propertiesFileName: String): Properties? {
return Properties().apply {
ObjectFactory::class.java.classLoader.getResourceAsStream(propertiesFileName).use { stream ->
load(stream)
}
}
}
Run Code Online (Sandbox Code Playgroud)
非常好,Kotlin!:P
问题是:这个方法.properties在里面查找文件src/main/resources.使用:
ObjectFactory::class.java.classLoader...
Run Code Online (Sandbox Code Playgroud)
它有效,但使用:
this.javaClass.classLoader...
Run Code Online (Sandbox Code Playgroud)
classLoader …
classloader ×10
java ×10
annotations ×1
dynamic ×1
hotswap ×1
inheritance ×1
kotlin ×1
plugins ×1
reflection ×1
singleton ×1