关于什么是 Java类加载器,有1000万篇文章和文档,以及如何**为什么*编写自己的...但他们似乎都在假设一些我找不到简单答案的东西!
我理解类加载器的工作:读取字节码并从中构造一个对象.不同的类加载器以不同的方式执行此操作
但是从来没有必须在我自己的代码中对类加载器API进行编码,而且从不必编写我自己的代码,我很难理解当ClassLoader自己的代码实际触发时.
例如:
public static void main(String[] args) {
Fizz fizz = new Fizz();
fuzz.buzz();
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个Fizz对象.在Fizz可以实例化之前,我们需要一个类加载器来启动并加载Fizz.class到其缓存中.这种情况何时何地发生?!?!它没有明确地出现在我的代码中所以它必须隐含在JRE中的某个地方......?
与这个问题相切,如果我编写自己的类加载器,WidgetClassLoader并且想要将其配置为加载我的所有应用程序的类,或者可能只是我的Fizz.class,我如何将其"绑定" WidgetClassLoader到我的应用程序中,以便它知道要使用哪个类加载器?我的代码是否需要显式调用此类加载器,还是像第一个示例一样隐式?提前致谢!
我一直在尝试设置一个自定义类加载器,它拦截类以打印出正在加载到应用程序中的类.类加载器看起来像这样
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("Loading: " + name);
return super.loadClass(name);
}
}
Run Code Online (Sandbox Code Playgroud)
它只是吐出它加载的所有类的名称.但是,当我尝试运行一些代码时,
import org.python.util.PythonInterpreter;
public class Scripts {
public String main(){
PythonInterpreter p = new PythonInterpreter();
p.exec("print 'Python ' + open('.gitignore').read()");
return "Success! Nothing broke";
}
}
Run Code Online (Sandbox Code Playgroud)
通过
MyClassLoader bcl = new MyClassLoader();
Class c = bcl.loadClass("Scripts");
Method m = c.getMethod("main");
String result = (String) m.invoke(c.getConstructor().newInstance());
Run Code Online (Sandbox Code Playgroud)
它打印出来
Loading: Scripts
Loading: java.lang.Object
Loading: java.lang.String
Loading: org.python.util.PythonInterpreter
Python build/
.idea/* …Run Code Online (Sandbox Code Playgroud) 为什么默认情况下use-context-classloader设置为true?
为什么Clojure不使用当前的类加载器?
我经常遇到一个问题,我必须在一个活动的几次调用之间保持状态(即经历几个onCreate()/ onDelete()循环).不幸的是,Android对此的支持非常糟糕.
作为一种保存状态的简单方法,我认为由于类只被类加载器加载一次,因此在静态Bundle字段中存储在活动的多个实例之间共享的临时数据是安全的.
但是,偶尔,当实例A创建静态包并在其中存储数据,然后被销毁,而实例B尝试从中读取时,静态字段突然变为NULL.
这是否意味着当活动进行创建/销毁循环时,类已被类加载器删除并重新加载?在以前引用对象时,静态字段怎么会突然变为NULL?
Java中类加载器的正确行为是:
因此,系统类路径中定义的类应始终首先加载.Tomcat定义了每个war的类加载器,它将系统类加载器作为父类,因此如果您尝试加载类,它将首先查看系统类路径,然后查看war文件中定义的类路径.
据我了解,这有两个原因:
所以,问题是:
除了上述问题之外,实现不首先进行父搜索的类加载器还有其他缺陷吗?
Tomcat 类加载器HOW-TO文档描述了4种不同的类加载器:
但是,在默认的catalina.properties文件中,还为共享和服务器类加载器定义了属性.在文件的默认版本中,这两个属性都是空的,注释说:
如果保留为空白,则"common"加载程序将用作Catalina的"共享"/"服务器"加载程序.
我无法找到有关这些类加载器的任何其他文档.我的问题是,共享和系统加载器相对于公共加载器的搜索顺序是什么?此外,这些类加载器的用途是什么?
我有一个类Formula,位于包中javaapplication4,我使用URLClassLoader加载.但是,当我从Test1位于同一个包中的另一个类调用它时,我无法访问其具有默认访问修饰符的方法(我可以访问公共方法).
我得到以下异常:
java.lang.IllegalAccessException:类javaapplication4.Test1无法使用修饰符""访问类javaapplication4.Formula的成员
如何从同一个包中访问在运行时加载的类的包私有方法?
我想使用不同的类加载器是一个问题,但不确定为什么(我已经设置了URLClassLoader的父级).
SSCCE再现问题(Windows路径) - 我想问题出在loadClass方法中:
public class Test1 {
private static final Path TEMP_PATH = Paths.get("C:/temp/");
public static void main(String[] args) throws Exception {
String thisPackage = Test1.class.getPackage().getName();
String className = thisPackage + ".Formula"; //javaapplication4.Formula
String body = "package " + thisPackage + "; "
+ "public class Formula { "
+ " double calculateFails() { "
+ " return 123; "
+ " } "
+ " public …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种通过重写字节代码并重新加载类来动态添加字段到线程的方法,不确定它是否完全可能.欢迎任何指示.我发现了一些关于修改和加载类的信息,我知道JRebel可以无缝地交换你的代码,但不确定这里是否适用相同的方法/工具.
这里的动机是探索理论上更好的替代线程本地对象.如果方法有效,我应该能够用注释替换本地线程,结果应该优于当前的JDK实现.
PS:请救我"所有邪恶言论的根源"
澄清用例:
想象一下,我有一个ThreadLocal类:
class A {
ThreadLocal<Counter> counter;
...
counter.get().inc()
}
Run Code Online (Sandbox Code Playgroud)
我想用注释替换它:
class A {
@ThreadLocal
Counter counter;
...
counter.inc()
}
Run Code Online (Sandbox Code Playgroud)
但是代替上面的代码生成我想改变Thread,这样Thread现在有一个Acounter字段,实际的代码将是:
class A {
// Nothing here, field is now in Thread
...
Thread.currentThread().Acounter.inc()
}
Run Code Online (Sandbox Code Playgroud) java classloader dynamic-class-loaders dynamic-class-creation
关于类加载的文章指出getClass()不应该在构造函数中调用该方法,因为:
对象初始化仅在构造函数代码的出口处完成.
他们给出的例子是:
public class MyClassLoader extends ClassLoader{
public MyClassLoader(){
super(getClass().getClassLoader()); // should not call getClass() because object
// initialization will be complete only at
// the exit of the constructor code.
}
}
Run Code Online (Sandbox Code Playgroud)
但是据我所知,本机final方法getClass()将始终返回该java.lang.Class对象实例的对象,无论它在何处被调用(在构造函数内或不在构造函数内).
将调用getClass()构造函数中曾经给我们带来的问题?
如果是这样,getClass()在构造函数中调用会给我们带来错误的一些例子是什么?