Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在我的自定义类加载器中是否有一种方法可以在我委托超级创建类时将类加载器附加到类?_Java_Classloader - Fatal编程技术网

Java 在我的自定义类加载器中是否有一种方法可以在我委托超级创建类时将类加载器附加到类?

Java 在我的自定义类加载器中是否有一种方法可以在我委托超级创建类时将类加载器附加到类?,java,classloader,Java,Classloader,我有这个堆栈跟踪,这是第一次加载这个类(我对这个类的断点有一个条件) 编译类加载器是我的(即这一个) 我想要以插件的方式加载这个类。getClass.getClassLoader返回CompilingClassLoader。相反,它的类加载器是AppClassLoader 这给插件开发人员带来了很多问题,因为目前的解决方法是线程上下文类加载器。有没有一种方法可以声明编译类加载器加载了它,但将其委托给超级类加载器 顺便说一下,临界线是上面链接中的第111行。我希望该行使用超级类为我创建类,但我希

我有这个堆栈跟踪,这是第一次加载这个类(我对这个类的断点有一个条件)

编译类加载器是我的(即这一个)

我想要以插件的方式加载这个类。getClass.getClassLoader返回CompilingClassLoader。相反,它的类加载器是AppClassLoader

这给插件开发人员带来了很多问题,因为目前的解决方法是线程上下文类加载器。有没有一种方法可以声明编译类加载器加载了它,但将其委托给超级类加载器

顺便说一下,临界线是上面链接中的第111行。我希望该行使用超级类为我创建类,但我希望它看起来像是我创建的类。当调用clazz.getClassLoader()时,返回的类应该返回“my”类加载器。这就解决了一大堆问题

编辑----------------------

经过进一步调查。编译类加载器非常复杂。您有这些类型的类

  • 标准java.lang类
  • webpieces启动类
  • 应用程序按需编译类
  • webpieces插件类位于应用程序类的下面和上面
  • 位于应用程序类之下和之上的库
  • 对于#1,一旦我点击main,其中许多像java.lang.Object都是由app classloader加载的,所以这必须始终保持为真,这样你就不会得到可怕的将X转换为X产生ClassCastException的结果

    对于#2,其中大多数在启动时也由app classloader加载

    对于#3,这是我们编译或重新编译的代码。为了重新编译,我们扔掉CompilingClassLoader,重新创建另一个,但缓存所有以前编译的类的字节,这些类没有改变

    对于#4和#5来说,这就是它变得非常棘手的地方!!!我们有一个ProdServerMeta(一个应用程序编译类),它引用webpieces中的插件,这些插件有时会加载其他需要编译的应用程序类。目前,我们为hibernate注入编译类加载器以避免出现问题

    我越想这一点,hibernate类现在就由AppClassLoader加载,因为当无法编译委托给父类的类时,我们返回null

    现在,我在编译类加载器时遇到了这些情况,这很难简化为下面的Jan Willem Gmelig Meyling的类加载器!主要是因为defineClass在这个例子中似乎是关键的,而且是缺失的(就像下面Olivier所说的非常重要)

    无论如何,我在尝试下面的类加载器时遇到了这些问题

    • 加载java.lang.*导致了SecurityException,因此我不得不委托它
    • 解决这个问题后,当slf4j尝试加载配置时,我从SAXParserFactoryImpl到SAXParserFactoryImpl遇到了ClassCastException
    第二个完全有意义,因为Server.main创建了一个记录器,然后每个创建记录器的类都会在CompilingClassLoader中创建它。这让我想到了

    我无法加载在加载应用程序之前加载的任何内容

    其次,作为一个面向客户的Web服务器,我也无法分辨应用加载前和加载后引用了什么

    我的结论是,没有解决方案,因为作为开发人员编写代码时,我扔掉了以前的类加载器,许多类必须继续存在,就像启动时AppClassLoader引用的Logger一样

    当然,如果我使用CompilingClassLoader启动,我可能有更好的机会“尝试”加载除java.lang以外的所有内容,但是,我仍然遇到这样一个问题:在服务器启动后,第一个编译类加载器将始终引用一些代码,而随后重新编译时的代码将指向一个新的编译类加载器

    我认为唯一的解决方案是插件必须使用ContextClassLoader,我越是仔细考虑这种情况,下面的Olivier在这一点上是正确的,这是不可能的

    谢谢,
    Dean

    类装入器首先从其父类装入器装入类。您应该能够通过简单地不为类加载器设置父类加载器来解决这个问题,并且自己委托调用
    loadClass

    一个有效的例子:

    public类SomeClass实现可运行{
    @凌驾
    公开募捐{
    System.out.println(“类的类加载器:+getClass().getClassLoader());
    System.out.println(“线程的类加载器:+thread.currentThread().getContextClassLoader());
    System.out.println(“传递依赖项的类加载器:+SomeDependency.Class.getClassLoader());
    }
    }
    
    可传递依赖项:

    public类SomeDependency{}
    
    测试和类加载器:

    import java.net.URL;
    导入java.net.URLClassLoader;
    公开课考试{
    公共静态类CustomClassLoader扩展了URLClassLoader{
    类加载器委托;
    公共CustomClassLoader(URL[]URL,ClassLoader父级){
    超级(URL,空);
    代表=家长;
    }
    @凌驾
    公共类loadClass(字符串名称)引发ClassNotFoundException{
    试一试{
    返回super.loadClass(名称);
    }catch(classnotfounde异常){
    返回delegate.loadClass(名称);
    }
    }
    }
    公共静态void main(字符串…参数)引发异常{
    URL位置=SomeClass.class.getProtectionDomain().getCodeSource().getLocation();
    CustomClassLoader CustomClassLoader=新CustomClassLoader(新URL[]{location},ClassLoader.getSystemClassLoader());
    
    Class loader for class: com.pkg.Test$CustomClassLoader@4e50df2e
    Class loader for thread: com.pkg.Test$CustomClassLoader@4e50df2e
    Class loader for transitive dependency: sun.misc.Launcher$AppClassLoader@18b4aac2