Kit*_*ten 5 java classloader java-platform-module-system java-9 java-module
我一直在使用Java中的简单自定义类加载器,到目前为止,一切都按预期用于非模块相关类.但是,我似乎无法找到使用我的类加载器从模块加载类的任何方法,即使模块相关的find*()方法已经重载.我试图做的是从模块"HelloModularWorld"加载一个类并运行它的主要.但是,当我指定包所在的目录时,它会"正常"加载并报告为未命名的模块.我错过了什么?
类加载器只是从文件系统的其他地方加载类,没什么特别的.
类加载器实现:
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) {...}
}
Run Code Online (Sandbox Code Playgroud)
测试代码:
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
}
}
Run Code Online (Sandbox Code Playgroud)
在线Class<?> clazz = mcl.loadClass("hellomodularworld/com.archdukeliamus.hellomodularworld.HelloWorld");我尝试过:
com/archdukeliamus/hellomodularworld/HelloWorld (wrong name: hellomodularworld/com/archdukeliamus/hellomodularworld/HelloWorld)编辑:module-info.java
module hellomodularworld {
}
Run Code Online (Sandbox Code Playgroud)
测试类不在任何模块中.(我不完全确定为什么这很重要,我应该得到一个例外,因为"这个包没有导出",我没有得到.)
编辑2:修改模块包括exports com.archdukeliamus.hellomodularworld;.结果没有变化.
模块加载是与类加载不同的过程。要在运行时加载模块,您需要使用该类创建一个新的模块层,并从 a (在本例中为磁盘)ModuleFinder提供 a 。然后,您将需要创建一个可用于解析模块的文件。为了确保模块加载过程的完整性,您需要导出引导配置。然后,您需要创建配置,包括告诉在哪里找到模块以及要解析的一组模块。然后实例化您希望用来加载这些模块的类的类加载器,并将其传递给定义模块方法。最后你实例化你的类。PathFileSystemConfigurationModuleFinder
新测试:
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...
}
}
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,这仍然没有调用重载的基于模块的 findClass() 方法,尽管它似乎有效。
| 归档时间: |
|
| 查看次数: |
650 次 |
| 最近记录: |