我一直在Java玩简单的自定义类加载器,到目前为止,对于非模块相关的类来说,一切都按照预期工作。但是,我似乎找不到任何方法来使用我的类加载器从模块加载类,即使与模块相关的find*()
方法已经被重载。我尝试做的是从模块“HelloModularWorld”加载一个类,并运行它的main。然而,当我指定包所在的目录时,它将“正常”加载,并报告为在未命名模块中。我错过了什么?
类加载器只是从文件系统的其他地方加载类,没有什么特别的。
类加载器实现:
package arch.classloaders;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
public class ModifiableClassLoader extends ClassLoader {
private File searchPath;
//...other ctors...
public ModifiableClassLoader(File path, String name, ClassLoader parent) {
super(name, parent); //Delegate to parent classloader as required.
if (!path.isDirectory()) throw new IllegalArgumentException("Path must be a directory");
searchPath = path;
}
public void setPath(File newPath) {...}
public File getPath() {...}
//Responsible for actual loading
public Class<?> findClass(String binName) throws ClassNotFoundException {
File classfile = new File(searchPath.getPath() + File.separator
+ binName.replace('.', File.separatorChar) + ".class");
byte[] buf;
FileInputStream fis;
try {
fis = new FileInputStream(classfile);
buf = fis.readAllBytes();
fis.close();
} catch (IOException e) {
throw new ClassNotFoundException("Error in defining " + binName + " in " + searchPath.getPath(),e);
}
return defineClass(binName, buf, 0, buf.length);
}
//Modules are expected to be in a folder with the same name as the module.
//e.g. module hellomodularworld is expected to be in a folder
//<SEARCHPATH>/<MODNAME>/
//NOTE: Module-overloaded methods return null rather than throw when class isn't found.
public Class<?> findClass(String modName, String binName) {
if (null == modName) {
try {
return findClass(binName);
} catch (ClassNotFoundException e) {
return null;
}
}
File classfile = new File(searchPath.getPath() + File.separator
+ modName + File.separator
+ binName.replace('.', File.separatorChar) + ".class");
byte[] buf;
FileInputStream fis;
try {
fis = new FileInputStream(classfile);
buf = fis.readAllBytes();
fis.close();
} catch (IOException e) {
return null;
}
return defineClass(binName, buf, 0, buf.length);
}
//Non-module
public URL findResource(String resPath) {...}
//Module version
public URL findResource(String modName, String resPath) throws IOException {...}
//Enumeration version; does nothing.
public java.util.Enumeration<URL> findResources(String resPath) {...}
}
测试代码:
public class Test {
public static void main(String[] args) {
ModifiableClassLoader mcl = new ModifiableClassLoader(
new File("C:\\Users\\archd\\Desktop\\"));
try {
Class<?> clazz = mcl.loadClass(
"hellomodularworld/com.archdukeliamus.hellomodularworld.HelloWorld"
);
java.lang.reflect.Method mth = clazz.getMethod("main", String[].class);
mth.invoke(null,new Object[] {null});
System.out.println(clazz.getModule().getName());
} catch (...) {
//omitted
}
}
在线类<?>clazz=mcl.loadClass(“hellomodularworld/com.archdukeliamus.hellomodularworld.helloworld”);
我已尝试:
com/archdukeliamus/hellomodularworld/helloworld(错误名称:hellomodularworld/com/archdukeliamus/helloworld)
编辑:module-info.java
module hellomodularworld {
}
测试类不在任何模块中。(我不完全确定这有什么关系,我应该得到一个“这个包不导出”的例外,但我没有得到。)
编辑2:修改模块,以包含导出com.archdukeliamus.hellomodularworld;
。结果没有变化。
模块加载是与类加载分离的过程。要在运行时加载模块,您需要使用ModuleFinder
类创建一个新的模块层,该类提供了来自文件系统
的路径
(在本例中为磁盘)。然后,您需要创建一个配置
来解析模块。为了确保模块加载过程的健全性,您将需要派生引导配置。然后需要创建配置,包括一个modulefinder
来告诉要在哪里找到模块,以及一组要解析的模块。然后实例化您希望用来加载这些模块的类的类加载器,并将其传递给define modules方法。最后,实例化您的类。
新测试:
package arch.classloaders;
import java.lang.module.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.io.*;
import java.nio.*;
import java.nio.file.*;
import java.util.*;
public class Test2 {
public static void main(String[] args) {
//Get paths to module, and instantiate a ModuleFinder.
Path pth = FileSystems.getDefault().getPath("C:\\Users\\archd\\Desktop");
ModuleFinder mf = ModuleFinder.of(pth);
//Create a new Configuration for a new module layer deriving from the boot configuration, and resolving
//the "hellomodularworld" module.
Configuration cfg = ModuleLayer.boot().configuration().resolve(mf,ModuleFinder.of(),Set.of("hellomodularworld"));
//Create classloader
ModifiableClassLoader mcl = new ModifiableClassLoader(
new File("C:\\Users\\archd\\Desktop\\"));
//make the module layer, using the configuration and classloader.
ModuleLayer ml = ModuleLayer.boot().defineModulesWithOneLoader(cfg,mcl);
//Show the configuration.
System.out.println(ml.configuration()); //prints "hellomodularworld"
try {
//load and run class
Class<?> clazz = ml.findLoader("hellomodularworld").loadClass(
"com.archdukeliamus.hellomodularworld.HelloWorld"
);
java.lang.reflect.Method mth = clazz.getMethod("main", String[].class);
mth.invoke(null,new Object[] {null});
//show the module this class is part of and list packages
System.out.println(clazz.getModule()); //prints "module hellomodularworld"
for (String pkgn : clazz.getModule().getPackages()) {
System.out.println(pkgn); //prints "com.archdukeliamus.hellomodularworld"
}
} catch (ClassNotFoundException e) {
...omitted...
}
}
}
有趣的是,这仍然没有调用重载的基于模块的findClass()方法,尽管它似乎可以工作。
本文向大家介绍java 类加载与自定义类加载器详解,包括了java 类加载与自定义类加载器详解的使用技巧和注意事项,需要的朋友参考一下 类加载 所有类加载器,都是ClassLoader的子类。 类加载器永远以.class运行的目录为准。 读取classpath根目录下的文件有以下几种方式: 1 在Java项目中可以通过以下方式获取classspath下的文件: 在Tomcat中tomcat又声明了
我试图修改几个类的字节代码,这些类的打包jar文件不在类路径中-它们是在给定URL的运行时由自定义的加载的。我尝试使用和来拦截那些类,但失败了。类加载器是遗留项目的一部分,因此我无法直接对其进行更改。 代理可以很好地处理AppClassLoader“本地”加载的类,但只会忽略那些由自定义类加载器加载的类。 CustomClassLoader: 我的代理中使用的ClassFileTransforme
问题内容: 我有一个Java类,它在启动时基于javassist类加载器创建自定义类加载器,然后运行实际的程序类。我收到以下错误: 该问题与以下事实有关:一个对象是由原始类加载器创建的,而另一个是由自定义类创建的。 有没有办法解决此错误? 在此先感谢 Avner 问题答案: 请尝试将-Dlog4j.ignoreTCL =true设置为希望有帮助。关于log4j的类似问题
问题内容: 我一直在尝试建立一个自定义的类加载器,该类加载器将拦截类以打印出哪些类正在加载到应用程序中。类加载器看起来像这样 它只是吐出它加载的所有类的名称。但是,当我尝试运行一些代码时, 通过 它打印出来 这似乎很奇怪。这不是一个简单的类,它取决于程序包中的许多其他类。这些类显然正在加载中,因为d python代码能够执行操作并读取我的文件。但是,由于某些原因,那些类并未由load的类加载器加载
问题内容: 是否可以为javac(或某些替代的Java编译器)指定自定义类加载器? 我很喜欢这种壮举,因为它可以让我编译使用仅由我的特殊类加载器找到的类的类。 对于那些好奇的人:我将编写一个连接数据库的classloder,并根据找到的表创建类。 问题答案: 运行javac时,您可以像这样指定类加载器:
我在JBoss7中部署了一个WAR,它使用上下文类加载器动态加载jar资源。 但是,上下文类加载器只在WEB-INF/lib文件夹中查找资源 Service Module Loader中模块“Deployment..war:main”的ModuleClassLoader 我如何在jboss中为我拥有资源的特定模块获取类加载器。我有需要加载到jboss_home/modules/org/custom