我有两个项目使用来自 AdoptOpenJDK 的 Java 11 和 ant 用于构建目的。除了命名之外,两者都使用相同的代码库。
第一个是非模块化项目,代码在未命名的模块中。这个运行没有异常并按预期添加库。
这是主类的代码:
package nonmodularsampleproject;
import java.lang.reflect.Field;
import java.util.Arrays;
/**
*
* @author Robert
*/
public class NonModularSampleProject {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
String installationDirectory = System.getProperty("user.dir");
String pathToAdd = installationDirectory + "\\" + "natives" + "\\" + "displays";
try {
addLibraryPath(pathToAdd);
} catch (Exception ex) {
System.err.println("Error while add the Native-Library-Path to the System.");
}
System.loadLibrary("displays");
}
private static void addLibraryPath(String pathToAdd) throws Exception {
Module baseModule = ClassLoader.class.getModule(), unnamedModule = NonModularSampleProject.class.getModule();
System.out.println("ClassLoader.class.getModule() " + ClassLoader.class.getModule());
System.out.println("ModularSampleProject.class.getModule() " + NonModularSampleProject.class.getModule());
System.out.println("module names: " + baseModule.getName() + " " + unnamedModule.getName());
try {
baseModule.addOpens("java.lang", unnamedModule);
} catch (IllegalCallerException ex) {
System.err.println("IllegalCallerException " + ex);
}
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[]) usrPathsField.get(null);
//check if the path to add is already present
for (String path : paths) {
if (path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length - 1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
}
第二个是模块化项目,其代码位于命名模块中。这个抛出一个异常。添加库失败。
这是模块信息的代码:
module ModularSampleProject {
requires java.base;
}
这是主类的代码:
package modularsampleproject;
import java.lang.reflect.Field;
import java.util.Arrays;
/**
*
* @author Robert
*/
public class ModularSampleProject {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
String installationDirectory = System.getProperty("user.dir");
String pathToAdd = installationDirectory + "\\" + "natives" + "\\" + "displays";
try {
addLibraryPath(pathToAdd);
} catch (Exception ex) {
System.err.println("Error while add the Native-Library-Path to the System.");
}
System.loadLibrary("displays");
}
private static void addLibraryPath(String pathToAdd) throws Exception {
Module baseModule = ClassLoader.class.getModule(), namedModule = ModularSampleProject.class.getModule();
System.out.println("ClassLoader.class.getModule() " + ClassLoader.class.getModule());
System.out.println("ModularSampleProject.class.getModule() " + ModularSampleProject.class.getModule());
System.out.println("Module names: " + baseModule.getName() + " " + namedModule.getName());
try {
baseModule.addOpens("java.lang", namedModule);
} catch (IllegalCallerException ex) {
System.err.println("IllegalCallerException " + ex);
}
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[]) usrPathsField.get(null);
//check if the path to add is already present
for (String path : paths) {
if (path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length - 1] = pathToAdd;
usrPathsField.set(null, newPaths);
}
}
stackoverflow 上的这两个其他很棒的帖子导致了这种方法。
在 Java 运行时为本地库添加新路径
如何使用 java 13+ 动态设置 java.library.path?
这篇文章也有很大帮助。
http://fahdshariff.blogspot.de/2011/08/changeing-java-library-path-at-runtime.html
在模块化项目中,调用 baseModule.addOpens("java.lang", namedModule) 会引发 IllegalCallerException,而在非模块化项目中,一切正常。
这是异常堆栈跟踪:
SCHWERWIEGEND: Error while open the package java.lang of the module java.base to the module ModularSampleProject
java.lang.IllegalCallerException: java.lang is not open to module ModularSampleProject
at java.base/java.lang.Module.addOpens(Module.java:762)
at ModularSampleProject/modularsampleproject.ModularSampleProject.addLibraryPath(ModularSampleProject.java:44)
at ModularSampleProject/modularsampleproject.ModularSampleProject.main(ModularSampleProject.java:28)
模块化项目有什么问题?