假设java代码库有一个名为"com.example"的包.
在运行时,我们可以通过调用获取此包
Package p = Package.getPackage( "com.example" ); //(returns null)
Run Code Online (Sandbox Code Playgroud)
甚至可以通过调用获得所有包的列表
Packages[] ps = Package.getPackages();
Run Code Online (Sandbox Code Playgroud)
问题是 - 如果ClassLoader尚未从包中加载任何类,则它们将无法用于这些函数调用.我们可以通过首先强制加载包中的一个类来强制它加载包,如下所示:
this.getClass().getClassLoader().loadClass( "com.example.SomeClass" );
Package p = Package.getPackage( "com.example" ); //(returns non-null)
Run Code Online (Sandbox Code Playgroud)
但是,这很hacky并且需要提前知道属于该包的某个类的名称.
所以问题是 - 有没有办法按名称获取Package的实例,无论ClassLoader是否做了什么?关于类加载/包在这种情况下如何工作的假设是否准确?
我需要不同的类加载器才能卸载类.但我需要在它们之间共享对象(实际上我得到的是ClassCastException).那么解决这个问题的解决方案是什么?谢谢
来自javadoc
只要线程处于活动状态且ThreadLocal实例可访问,每个线程都会保存对其线程局部变量副本的隐式引用; 在一个线程消失之后,它的所有线程局部实例副本都要进行垃圾收集(除非存在对这些副本的其他引用).
从那看起来,ThreadLocal变量引用的对象只有在线程死亡时才会被垃圾收集.但是如果ThreadLocal变量a不再被引用并且是垃圾收集的呢?a如果持有的线程a仍然存活,那么仅由变量引用的对象是否会被垃圾回收?
例如,以下类具有ThreadLocal变量:
public class Test {
private static final ThreadLocal a = ...; // references object b
}
Run Code Online (Sandbox Code Playgroud)
此类引用一些对象,此对象没有其他引用.然后在上下文取消部署期间,应用程序类加载器成为垃圾收集的主题,但线程来自线程池,因此它不会死亡.对象b是否会被垃圾收集?
要在JVM中调试类加载,我们可以使用param -verbose:class,但是......任何人都知道如何调试资源加载(例如属性文件)?
到目前为止,我看到的自定义ClassLoader示例涉及子类化URLClassLoader,并使用该特定实例加载资源中的类.
我徒劳地试图寻找替换SystemClassLoader的替代方法,以便可以为不在类路径中的类查询我的ClassLoader.
我试过了Thread.currentThread().setContextClassLoader,但似乎没有用.
它甚至可能吗?
我在sdCard上有1个.jar文件(我使用dx工具编译通常的.jar到dex ..否则android会在运行时抱怨)
我想要使用的课程实际上是一个活动&通过"使用"我的意思是膨胀!
A)我注意到如果我像这样加载类,加载的类将包含parrent类的包(我运行代码的那个:示例:jar库中的类的真实包:"com .something"&my-app-package:"com.wonderfull" - >加载的类在"com.wonderfull.com.something":)) - >重新测试:它保留原始包,就像在库中一样
B)在"最佳"情况下,我收到此错误:
无法实例化活动ComponentInfo {com.appno2/com.appno1.futureLib.LibActivity}:java.lang.ClassNotFoundException:com.appno1.futureLib.LibActivity in loader dalvik.system.PathClassLoader [/data/app/com.appno2-1 apk文件]
C)在清单中我已经放置了Activity(一个要加载的动态),如下所示:
activity android:name ="com.appno1.futureLib.LibActivity"android:label ="@ string/app_name">/activity>
所以我从标题重复提问:是否有可能从sdCard上的jar库中加载一个Activity类并实际使用它?
在"为什么你想要这个?"的情况下. - 只是古玩!+作为一个概念:在用户输入有效许可证后,可以下载app的实际代码(以jar的形式)
更新: - 此ideea适用于片段(意味着要导入的类是片段)
目前的结论: - 可能有:lame java类甚至是外部.jar中的android UI相关类(例如,在sdCard上,或者从internet..etc下载)并根据需要加载它们.哦是的:你不能以这种方式工作这个活动:(甚至可能不是服务..
更多信息#1:是否可以在运行时从Android应用程序动态加载库?
更多信息#2:http://android-developers.blogspot.ro/2011/07/custom-class-loading-in-dalvik.html
Regardin URLClassLoader:这是有效的(不涉及DalvikClassLoader - ClassNotFoundException && obviosly:仍然无法膨胀像这样加载的活动)
File file = new File("/sdcard/myLib.jar");
File tmpDir = getDir("dex", 0);
ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader());
DexClassLoader classloader = new DexClassLoader(file.getAbsolutePath(), tmpDir.getAbsolutePath(), null, loader);
Class<Object> classref = (Class<Object>) classloader.loadClass("packageInLib.ClassName");
Object myInstance …Run Code Online (Sandbox Code Playgroud) 所以我有一个类加载器(MyClassLoader),它在内存中维护一组"特殊"类.这些特殊类是动态编译的,并存储在MyClassLoader内的字节数组中.当MyClassLoader被要求提供类时,它首先检查它的specialClasses字典是否包含它,然后再委托给System类加载器.它看起来像这样:
class MyClassLoader extends ClassLoader {
Map<String, byte[]> specialClasses;
public MyClassLoader(Map<String, byte[]> sb) {
this.specialClasses = sb;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (specialClasses.containsKey(name)) return findClass(name);
else return super.loadClass(name);
}
@Override
public Class findClass(String name) {
byte[] b = specialClasses.get(name);
return defineClass(name, b, 0, b.length);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我想在其上执行转换(例如检测)specialClasses,我可以简单地通过修改byte[]之前调用defineClass()它来实现.
我还想转换由System类加载器提供的类,但是System类加载器似乎没有提供任何方式来访问byte[]它提供的类的原始类,并Class直接给我提供了对象.
我可以使用一个-javaagent仪器加载到JVM中的所有类,但这会增加我不想检测的类的开销; 我只是想要MyClassLoader加载的类进行检测.
byte[]父类加载器提供的类的原始,所以我可以在定义自己的副本之前检测它们?byte[],以便MyClassLoader可以检测和定义自己的所有System类(Object,String等)的副本?编辑:
所以我尝试了另一种方法:
-javaagent,捕获 …我在Java 6上,我有一个方法可以扫描运行时类路径中的文件config.xml.如果找到,我想将文件的内容读成字符串:
InputStream istream = this.getClass().getClassLoader().getResourceAsStream("config.xml");
if(istream != null) {
System.out.println("Found config.xml!");
StringBuffer fileData = new StringBuffer(1000);
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(fileName));
char[] buf = new char[1024];
int numRead = 0;
while((numRead=reader.read(buf)) != -1) {
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
buf = new char[1024];
reader.close();
}
} catch (FileNotFoundException fnfExc) {
throw new RuntimeException("FileNotFoundException: " + fnfExc.getMessage());
} catch (IOException ioExc) {
throw new RuntimeException("IOException: " + ioExc.getMessage());
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,我得到以下控制台输出:
Found …Run Code Online (Sandbox Code Playgroud) 如何让JUnit ClassLoader为它执行的每个测试类使用一个单独的?
我正在TestRunner为一个设置很多静态变量的库编写一个JUnit .我基本上想要在每个测试类之间重置所有这些,而不需要知道它们是什么.我不想加入对框架的深入了解,因为每当库内部发生变化,我的TestRunner意志就会破裂.
在我进一步发展之前,我想明确表示我确实想要这样做.
我可以在StackOverflow上找到的其他答案只是说"不要那样做",这没有用.第一个回答"静态变量愚蠢"的人赢得了甜甜圈.