gpt4 book ai didi

java - 如何让类加载器在初始化静态对象之前评估类路径?

转载 作者:行者123 更新时间:2023-12-02 00:44:12 25 4
gpt4 key购买 nike

我正在开发一个应用程序,它同时使用 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com