- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个应用程序,它同时使用 jar 库和 native 系统库。我的问题是默认类加载器在调用 main 之前很久就尝试加载静态类。由于类路径尚不包含静态类所需的 native 库,因此在第一次评估静态引用时会抛出 java.lang.NoClassDefFoundError 。
这是我无法访问的库加载方法的样子:
private static void load_libraries() {
try {
String osname = getOSName();
if (osname == null) {
throw new RuntimeException("The system you are running on is not supported");
}
URL u = NativeLibs.class.getResource(osname);
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class urlClass = URLClassLoader.class;
Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(urlClassLoader, new Object[]{u});
} catch (IllegalAccessException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex);
} catch (SecurityException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to load native libs", ex);
}
}
那么,让我解释一下这里发生了什么。首先, getOSName() 所做的只是返回一个代表我正在运行的操作系统系列的字符串。如果操作系统不受支持,则返回 null。以防万一我在该方法中遇到问题,我也会继续发布它:
private static String getOSName() {
String os = System.getProperty("os.name").toLowerCase(Locale.US);
if (os.indexOf("win") >= 0) {
return "windows";
} else if (os.indexOf("mac os x") >= 0) {
return "macosx";
} else if (os.indexOf("nux") >= 0) {
return "linux";
} else if (os.indexOf("solaris") >= 0) {
return "solaris";
} else {
return null;
}
}
它返回的字符串是方法 load_libraries() 用来定义相对 URL 的目录名称,我以反射方式传递给类加载器以加载库。我的问题是,运行时执行永远不会到达 load_libraries(),即使这是 main 中的第一个方法。
一个显而易见的解决方案是使用定制的 jar 静态加载 native 库。如果完全可以避免的话,我不想静态链接 native 库,因为这违背了 java 平台可移植性的目的。我已经推导出的另一个解决方案是一个系统可执行文件,它可以使用系统可执行文件中确定的自动类路径运行应用程序 jar,但该解决方案仍然需要多个特定于平台的可执行文件。
所以,这是我的问题:
我可以强制类加载器在初始化静态对象之前运行我的库加载方法吗?这需要定制的类加载器吗?如果它确实需要自定义类加载器,那么只需传递代表默认类加载器的系统属性就可以解决问题吗?
谢谢,我希望我写了一个足够详细的问题!
最佳答案
“默认类加载器在调用 main 之前很久就尝试加载静态类”的原因是因为您的主类具有静态成员变量和/或静态初始值设定项。当类加载器初始化主类时,它还必须初始化这些静态变量。欲了解更多信息,请参阅VM Spec .
解决方案 - 唯一好的解决方案 - 是消除静态初始化。在 main()
中初始化静态成员变量,或使用 Spring 等框架来进行初始化。
一般来说,静态成员变量很少有好的用途。其中大多数最终都是黑客提供从程序中任意点访问资源的方法。这不仅使程序更难测试,还会导致意外的初始化链。
关于java - 如何让类加载器在初始化静态对象之前评估类路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5450419/
我是一名优秀的程序员,十分优秀!