如何为嵌套的JAR文件创建自定义的ClassLoader

问题描述 投票:0回答:2

我正在使用Java库,该库在lib程序包中具有一些嵌套的JAR文件。

我有2个问题:

  1. 我在我的IDE中看不到引用的类型(我正在使用JetBrains IntelliJ)
  2. 当然,我得到的类在运行时未定义

我知道我必须创建并使用自定义的ClassLoader,它可以解决这两个问题吗?这是获得此结果的推荐方法吗?

JAR文件是意大利政府提供的库,由于法规会定期更新,因此我无法对其进行修改。

java classloader
2个回答
0
投票

我不知道装完罐子后要做什么。就我而言,对Servlet示例使用jar动态加载。

    try{
    final URLClassLoader loader = (URLClassLoader)ClassLoader.getSystemClassLoader();
    final Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    method.setAccessible(true);

    new File(dir).listFiles(new FileFilter() {
        @Override
        public boolean accept(File jar) {

            // load file if it is 'jar' type
            if( jar.toString().toLowerCase().contains(".jar") ){
                try {
                    method.invoke(loader, new Object[]{jar.toURI().toURL()});
                    XMLog.info_arr(logger, jar, " is loaded.");

                    JarInputStream jarFile = new JarInputStream(new FileInputStream(jar));
                    JarEntry jarEntry;

                    while (true) {
                        // load jar file
                        jarEntry = jarFile.getNextJarEntry();
                        if (jarEntry == null) {
                            break;
                        }

                        // load .class file in loaded jar file
                        if (jarEntry.getName().endsWith(".class")) {
                            Class loadedClass = Class.forName(jarEntry.getName().replaceAll("/", "\\.").replace(".class",""));

                            /*
                            * In my case, I load jar file for Servlet.
                            * If you want to use it for other case, then change below codes
                            */
                            WebServlet annotaions =  (WebServlet) loadedClass.getAnnotation(WebServlet.class);

                            // load annotation and mapping if it is Servlet
                            if (annotaions.urlPatterns().length > 0) {
                                ServletRegistration.Dynamic registration = servletContextEvent.getServletContext().addServlet(annotaions.urlPatterns().toString(), loadedClass);
                                registration.addMapping(annotaions.urlPatterns());
                            }
                        }
                    }
                } catch (Exception e) {
                    System.err.println("Can't load classes in jar");
                }
            }
            return false;
        }
    });
} catch(Exception e) {
    throw new RuntimeException(e);
}

0
投票

是,据我所知,标准的ClassLoader不支持嵌套JAR。

如果要从其他人那里获得这些JAR,最好的办法是与供应商联系,并要求他们提供标准兼容格式的产品。从您的回答中,我意识到这可能很难实现,但是我仍然会尝试与他们交谈,因为这是正确的做法。我很确定您所处位置的其他所有人都有同样的问题。根据行业标准,这种情况通常会提示您的供应商将Maven存储库用于其可交付成果。

如果与您的供应商交谈失败,您可以在收到JAR时重新打包它们。我建议为此编写一个自动化脚本,并确保它在每次交付时都运行。您可以将所有.class文件放入一个uber-JAR中,也可以将嵌套的JAR移到封闭的JAR之外。注意事项1:可以有多个同名课程,因此您需要确保选择正确的一个。注意事项2:如果JAR已签名,则您将丢失签名(除非您用自己的签名)。

选项3:您始终可以实现自己的ClassLoader,以从任何地方(甚至从厨房水槽)加载类。

此人正是这样做的:https://www.ibm.com/developerworks/library/j-onejar/index.html

您可以将他的解决方案用作“包装程序加载器”,它将替换您的主类。

就IntelliJ IDEA而言,我不认为它支持现成的功能。最好的办法是如上所述重新打包JAR并将其添加为单独的类路径条目,或者搜索是否有人编写了用于嵌套JAR支持的插件。

© www.soinside.com 2019 - 2024. All rights reserved.