简体   繁体   English

Java:自动自定义ClassLoader

[英]Java: Automatic Custom ClassLoader

My application uses the Standard Widget Toolkit (SWT) for it's GUI. 我的应用程序的GUI使用了标准小部件工具包(SWT)。 My problem is that the 32-bit SWT library does not work on a 64-bit JVM. 我的问题是32位SWT库在64位JVM上不起作用。 But I don't want to make people select the correct architecture when getting the software. 但是我不想让人们在获取软件时选择正确的体系结构。 So, I want to bundle both the 32-bit and 64-bit libraries, and auto-detect the architecture during runtime. 所以,我希望捆绑 32位和64位库,并在运行时自动检测架构。 I found out I can get the correct architecture of the JVM like so: 我发现我可以得到正确的JVM体系结构,如下所示:

if (System.getProperty("os.arch").contains("64")) {
    // ...
}

Now all that's left is to load the jar. 现在剩下的就是加载罐子了。 But the problem is, all the examples I found require that you manually load the class before using it. 但是问题是,我发现的所有示例都要求您在使用类之前手动加载该类。

Class.forName("MyClass", false, myClassLoader);

So my question is, is it possible to "register" my class loader, so that I don't have to load classes beforehand? 所以我的问题是,是否可以“注册”我的类加载器,这样我就不必事先加载类?


Update: I created my own child class of URLClassLoader and set it as the default class loader with the command line argument -Djava.system.class.loader ; 更新:我创建了自己的URLClassLoader子类,并使用命令行参数-Djava.system.class.loader将其设置为默认类加载器; but I get this error: 但是我得到这个错误:

Error occurred during initialization of VM
java.lang.Error: java.lang.NoSuchMethodException: com.program.LibraryLoader.<init>(java.lang.ClassLoader)
    at java.lang.ClassLoader.initSystemClassLoader(Unknown Source)
    at java.lang.ClassLoader.getSystemClassLoader(Unknown Source)

I think LibraryLoader.<init> refers to the constructor... but it's there ( public LibraryLoader(URI[] urls) ). 我认为LibraryLoader.<init>是指构造函数...但是它在那里( public LibraryLoader(URI[] urls) )。


Update 2: Almost there, the JVM runs now. 更新2: JVM即将运行。 I added this constructor to make it work: 我添加了此构造函数以使其工作:

public LibraryLoader(ClassLoader classLoader) {
    super(new URL[0], classLoader);
}

But after adding the jars with addPath() ( file:lib/jars/swt.jar ), it only produces a NoClassDefFoundError . 但是在使用addPath()file:lib/jars/swt.jar )添加jar之后,它只会产生NoClassDefFoundError Yes, I double-checked that the file exists. 是的,我仔细检查了文件是否存在。

You could try to inject your custom class loader by means of the "java.system.class.loader" property (see ClassLoader#getSystemClassLoader). 您可以尝试通过“ java.system.class.loader”属性注入自定义类加载器(请参见ClassLoader#getSystemClassLoader)。 However, I'd recommend to use OSGi and let the framework do the complicated stuff. 但是,我建议使用OSGi,并让框架执行复杂的工作。

As part of the constructor for your custom ClassLoader, call definePackage with the appropriate information, with the URL pointing to the desired jar file. 作为自定义ClassLoader的构造函数的一部分,使用适当的信息调用definePackage,URL指向所需的jar文件。

This example shows that the custom class loader is called when I try to instantiate a class from swing, because I defined my class loader as the loader of that package. 此示例说明,当我尝试从swing实例化类时,将调用自定义类加载器,因为我将类加载器定义为该程序包的加载器。

import java.net.URL;

public class junk extends ClassLoader {

  byte[] dummy = new byte[0];

  public static void main(String[] args) throws Exception {
    new junk();

    new javax.swing.JPanel();

  }

  public junk() throws Exception {
    definePackage("javax.swing","","","","","","",new URL("file://junk.class"));
  }

  public Class<?> findClass(String s) throws java.lang.ClassNotFoundException{
    Class<?> retVal = super.findClass(s);

    System.out.println("delegated responsibility for "+s+" to superclass");

    return retVal;
  }

  public Package getPackage(String s) {
    Package retVal = super.getPackage(s);

    System.out.println("delegated responsibility for "+s+" to superclass");

    return retVal;
  }

}

Result: 结果:

delegated responsibility for javax.swing to superclass 将javax.swing的委托委托给超类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM