Java 在同一Dalvik/JVM中使用不同类加载器实例化的类不能;见;彼此
我正在开发一个带有pluggable.jar模块的Android应用程序 我的问题是,当我加载两个不同的.jar文件时,第一个.jar文件中的类无法从第二个.jar文件中“看到”(Class.forName())类,反之亦然。我使用DexClassLoader从主应用程序加载外部.jars ==下面是一个示例情况=== 我们有两个模块:Java 在同一Dalvik/JVM中使用不同类加载器实例化的类不能;见;彼此,java,android,jar,classloader,dalvik,Java,Android,Jar,Classloader,Dalvik,我正在开发一个带有pluggable.jar模块的Android应用程序 我的问题是,当我加载两个不同的.jar文件时,第一个.jar文件中的类无法从第二个.jar文件中“看到”(Class.forName())类,反之亦然。我使用DexClassLoader从主应用程序加载外部.jars ==下面是一个示例情况=== 我们有两个模块: First.jar(包含类FirstA和FirstB,打包在classes.dex中) Second.jar(使用类SecondA,同样在classes.de
- First.jar(包含类FirstA和FirstB,打包在classes.dex中)
- Second.jar(使用类SecondA,同样在classes.dex中)
- 所有模块都在运行时加载李>
- 每个模块都由不同的DexClassLoader实例加载,因为我需要提供.jar文件的路径,并且我不能将所有模块打包在一个jar中
- 模块1(模块1.jar,类为ClassModule1)
- 模块2(带有ClassModule2类的模块2.jar)
- 这是标准的Java行为;为了使类A对类B可见,类A必须由类B的装入器或其父类之一装入。事实上,不同的类加载器可以具有名称相同的不同JVM类
除非您有特定的理由不这样做,否则您通常应该对所有类/JAR使用相同的类加载器。如果确实有充分的理由,则需要确保加载程序之间具有适当的父/子关系
Java类加载的语义模型位于中。Dalvik通常遵循语义,尽管我不太了解这些差异。这是标准的Java行为;为了使类A对类B可见,类A必须由类B的装入器或其父类之一装入。事实上,不同的类加载器可以具有名称相同的不同JVM类 除非您有特定的理由不这样做,否则您通常应该对所有类/JAR使用相同的类加载器。如果确实有充分的理由,则需要确保加载程序之间具有适当的父/子关系
Java类加载的语义模型位于中。Dalvik通常遵循语义,但我对这些差异并不了解。警告:非常难看的“解决方案” 假设这两个模块加载了不同的DexClassLoader(在不同的场合,通过不同的线程等):
Class class = Class.forName("com.example.app.ClassModule2", false, ClassModule1.class.getClassLoader());
我们应该这样做:
ClassLoader dexClassLoader = new DexClassLoader(
manager.getPluginsFolder() + "Module-2.jar",
this.context.getApplicationContext().getFilesDir().getAbsolutePath(),
null,
ClassModule1.class.getClassLoader()
);
Class class = Class.forName("com.example.app.ClassModule2", true, dexClassLoader);
这很难看,因为有几件事:
- 由于forName()上的第二个参数“true”,我们正在再次确定加载模块
- 我们必须知道Module-2.jar的路径,这是不好的,因为模块是由ModuleManager管理的,而不是由模块本身管理的(职责分离)
感谢您的帮助。警告:非常难看的“解决方案” 假设这两个模块加载了不同的DexClassLoader(在不同的场合,通过不同的线程等):
- 模块1(模块1.jar,类为ClassModule1)
- 模块2(带有ClassModule2类的模块2.jar)
Class class = Class.forName("com.example.app.ClassModule2", false, ClassModule1.class.getClassLoader());
我们应该这样做:
ClassLoader dexClassLoader = new DexClassLoader(
manager.getPluginsFolder() + "Module-2.jar",
this.context.getApplicationContext().getFilesDir().getAbsolutePath(),
null,
ClassModule1.class.getClassLoader()
);
Class class = Class.forName("com.example.app.ClassModule2", true, dexClassLoader);
这很难看,因为有几件事:
- 由于forName()上的第二个参数“true”,我们正在再次确定加载模块
- 我们必须知道Module-2.jar的路径,这是不好的,因为模块是由ModuleManager管理的,而不是由模块本身管理的(职责分离)
ArrayList
)。不要调用Class.forName(“ClassIWant”)
,而是编写一个方法,迭代每个类加载器并调用ClassLoader\loadClass(“ClassIWant”)
我假设您的代码负责加载每个插件,这意味着您有一个对