【问题标题】:problem with dynamic class loading in javajava中动态类加载的问题
【发布时间】:2011-08-13 20:03:02
【问题描述】:

嗨,我有一个将类文件加载到我的程序中的代码。当我从 Eclipse 运行/调试它时,我总是从我的 bin 目录中选择类文件。当我将程序编译成 JAR 文件时,加载不起作用。 这些是加载类文件的行

public void load_dynamic_tag(String file_path)
            throws MalformedURLException, ClassNotFoundException,
            InstantiationException, IllegalAccessException {
        File f = new File(file_path);// some folder's path
        URI uri = f.toURI();
        URL url = uri.toURL();
        URL[] urls = new URL[] { url };
        // create a new class loader for this directory
        ClassLoader cl = new URLClassLoader(urls);
        // load the class file "MyAlgo.class"
        String name = f.getName();
        name = name.substring(0, name.lastIndexOf("."));
        name = "Tagging." + name;
        @SuppressWarnings("unchecked")
        Class<TaggingStrategy> c = (Class<TaggingStrategy>) cl.loadClass(name);
        // TaggingStrategy tag=c.newInstance();
        tag = c.newInstance();
    }

这是我得到的错误

java.lang.ClassNotFoundException: Tagging.Tag_by_lenght_filename
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at Tagging.Tags_all.load_dynamic_tag(Tags_all.java:233)
        at Command.LoadTagCommandExecutor.execute(LoadTagCommandExecutor.java:24
)
        at GUI.DropBox$2.handleEvent(DropBox.java:248)
        at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
        at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
        at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
        at GUI.DropBox.showGUI(DropBox.java:168)
        at GUI.Try_control$5.handleEvent(Try_control.java:135)
        at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
        at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
        at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
        at GUI.Try_control.<init>(Try_control.java:161)
        at GUI.NewSWTApp$2$1$2.run(NewSWTApp.java:121)
        at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
        at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
        at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4041)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3660)
        at Service.Main.main(Main.java:79)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)

我做错了什么? tnx分配

【问题讨论】:

    标签: java class dynamic classloader


    【解决方案1】:

    我的猜测是文件路径不再有效,您的类在 .jar 文件中,因此普通的文件不会这样做。 您需要做的是在 .jar 文件中找到类文件:

    File myFile = new File(YourClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()));
    JarFile myJar = new JarFile(myFile);
    

    然后获取jar里面的条目如下:

    Enumeration entries = jar.entries();
    

    现在,请参阅有关 Enumeration 如何列出类文件的文档。 (遍历所有文件,选择以 .class 结尾的文件)从这里,您知道类名,因此可以加载它。

    【讨论】:

    • 如果我想从 jar 文件中添加一个类?
    • 如果类文件不在 jar 文件中,您应该能够只提供一个绝对路径。请注意,该类所在的包必须与目录结构匹配,请参见exampledepot.com/egs/java.lang/LoadClass.html 上的示例(另外,您可能需要将路径中的斜杠替换为点),className = classPath.replace('/','. ')
    【解决方案2】:

    其实你需要做的就是把你的jar文件放到类路径中并调用

    Class<TaggingStrategy> c = (Class<TaggingStrategy>)Class.forName("Tagging.MyAlgo");
    

    如果“Tagging.Tag_by_lenght_filename”是您要加载的类的正确名称,那么您的问题很可能只是您的 jar 不在类路径中。

    如果您不想在类路径中包含 jar,则需要创建一个 URLClassLoader,其 URL 指向您的 jar 文件:

    URLCLassLoader myCL = new URLClassLoader(new URL[]{new File("path/to/myjar.jar").toURI().toURL()});
    

    如果您希望您的代码在这两种情况下都能正常工作,您需要确保您的 URL 指向 eclipse 中的 bin 目录并指向 jar 文件,以防您想使用已编译的 jar 文件。

    如果您需要发现哪些类文件可用,您可以使用文件系统抽象层 (FileSystems),它可以从目录或 jar 文件创建文件系统。

    【讨论】:

      【解决方案3】:

      URLClassLoader 在目录和 jar 文件中查找类。无论您以“file_path”的形式传入什么,都必须是包含您要查找的类的 jar 或目录的路径。如果是目录,则应以“/”结尾。也许您正在使用相对文件路径,根据它的运行位置,它会有不同的含义。传入了什么,类在哪里?

      【讨论】:

      • 我尝试使用 Path p = Paths.get(class_file_path); 发送完整路径File class_file = new File(p.toAbsolutePath().toString());但它没有用
      • 是的,请再次阅读我的答案。类文件的路径是无用的。给它一个目录或 jar 文件,就像您将目录或 jar 添加到类路径以进行编译或运行一样。例如。如果您的班级是 com.foo.Bar,则该文件将位于 /com/foo/Bar.class。您需要将“”传递给 ClassLoader 才能找到类 Bar。
      猜你喜欢
      • 1970-01-01
      • 2011-04-04
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 2016-03-12
      相关资源
      最近更新 更多