Java扩展应用程序类加载器?

问题:我的公司有很多不同的罐子/现有项目,它们在客户中运行。 为了进行调试,我们希望生成一个日志,其中每个组件加载哪个类,更具体地说: 从哪里开始 。 例如:jar StackOverFlowJar.jar中的stack.overflow.ClassA。

我的想法:我已经尝试将每个jar /现有项目传递给一个自定义类加载器。 这个自定义类加载器可能会将上面的信息写入文件,并将正常的类加载流委派给其父代。

我的CustomClassLoader扩展了ClassLoader,我可以看到它加载类如:

java.lang.Class
java.lang.Thread
java.lang.ThreadGroup

等等,核心库中的所有标准Java类。 这些类可以到达我的CustomClassLoader。 但是,如下图所示:

测试 来源:http://javarevisited.blogspot.nl/2012/12/how-classloader-works-in-java.html

有多个ClassLoaders。 引导类加载器(我用我的CustomClassLoader扩展的那个)只负责核心库。 如果找不到自定义创建的类,它将把它委托给扩展类加载器。 如果扩展类加载器找不到它,它会将它委派回应用程序类加载器,并且我可以在调试模式中看到,这确实是加载我的自定义类的一个。 但它不通过我的CustomClassLoader。

我的问题:是否可以扩展Application ClassLoader和扩展ClassLoader? 或者,对于我的问题,或许还有另一种解决方法?

非常感谢您提前!


您可以创建一个简单的Jar文件,在类路径中使用该Jar来运行该文件。 然后你可以有一个扩展了URLClassLoader的类,将这个对象传递给你真实的类路径,通过你的ClassLoader加载你的真正的主类,并且使用反射调用main方法。

示例主要方法

  public static void main (String... args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    URL[] classpath = new URL[0];

    LoggingClassLoader loggingClassLoader = new LoggingClassLoader(classpath, Main.class.getClassLoader());
    Class<?> aClass = loggingClassLoader.loadClass("com.company.project.RealMain");
    Method main = aClass.getMethod("main", args.getClass());
    main.invoke(null);

  }

示例类加载器对象

编辑

我稍微扩展了这个例子,现在每个jar / URL有一个加载器,以防你需要跟踪从哪个jar加载哪个类:

  public static class LoggingClassLoader extends URLClassLoader {
    final List<ChildLogger> childLochildLoggersders = new ArrayList<>();

    public LoggingClassLoader(URL[] urls, ClassLoader parent) {
      super(urls, parent);
      for(URL url : urls) {
        childLochildLoggersders.add(new ChildLogger(url, this));
      }
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
      for(ChildLogger childLoader : childLochildLoggersders) {
        try {
          return childLoader.loadClass(name);
        } catch(ClassNotFoundException ignore) {
        }
      }
      throw new ClassNotFoundException(name);
    }

    private static class ChildLogger extends URLClassLoader {
      private final URL url;

      private ChildLogger(URL url, ClassLoader parent) {
        super(new URL[]{url}, parent);
        this.url = url;
      }

      @Override
      protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> aClass = super.findClass(name);
        System.out.println("Loaded from :" + url + " class: " + name);
        return aClass;
      }
    }

  }

你也可以使用

-verbose:类

JVM选项可打印加载类的位置。 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

链接地址: http://www.djcxy.com/p/44397.html

上一篇: Java extend Application Classloader?

下一篇: java.lang.NoClassDefFoundError, Ant task could not see classes in jar inside jar