简体   繁体   English

Java,自定义类加载器的问题

[英]Java, problems with custom classloader

i'm writing a custom class loader to load some of my classes (not all). 我正在编写一个自定义类加载器来加载一些我的类(不是全部)。

Class loader are very simple: 类加载器非常简单:

public Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
    Class cls=findLoadedClass(className);
    if(cls!=null) {
        return cls;
    }
    // Search first for encrypted classes
    cls=decryptClass(className);
    if(cls==null) {
        // Then try with default system classloader
        cls=super.loadClass(className, resolve);
    }
    return cls;
}

And this is how i use it: 这就是我的使用方式:

// In my Launcher class
public static void main(String[] args) {
    MyClassLoader loader=new MyClassLoader();
    try {
        final Class main=loader.loadClass("com.MyAppMain");
        Method toInvoke=main.getMethod("main", args.getClass());
        toInvoke.invoke(main, new Object[]{args});
    }
    catch(Exception ex) {
    }
}

All seem to be fine in my small test project, but when i use this loader in my big project(client-server application that use spring+hibernate and IoC) doesn't work. 在我的小型测试项目中,一切似乎都很好,但是当我在大型项目(使用spring + hibernate和IoC的客户端-服务器应用程序)中使用此加载程序时,则无法正常工作。 I have not a particolar exception in my classloader, but for example, new Socket instance throw a "java.net.ConnectException: Connection refused" without a real reason... 我的类加载器中没有特别的异常,但是例如,新的Socket实例抛出“ java.net.ConnectException:连接被拒绝”而没有真正的原因...

Other problems is my main form does not become visible... and other strange problems like this. 其他问题是我的主要形式不可见...和其他类似的奇怪问题。

So, the question, are these problems caused by my classloader that load in different way a different kind of classes? 那么,问题是,这些问题是由我的类加载器以不同方式加载的不同类导致的吗?


Edit 1 编辑1

My project use spring, so i use @Autowired or sometimes 我的项目使用spring,所以我有时使用@Autowired

springApplicationContext.getBean(clazz);

to inject a bean. 注入豆子。

The problem is spring cannot find my beans if these classes are encrypted(so they need to be loaded by my classloader). 问题是,如果这些类被加密,spring将无法找到我的bean(因此它们需要由我的类加载器加载)。 There is a workaround for this mistake? 有针对此错误的解决方法吗? Thanks. 谢谢。


Edit 2 编辑2

I have set my classloader in spring ClassPathXmlApplicationContext and now i notice that spring uses my classloader to load beans class, but despite this it throws an org.springframework.beans.factory.NoSuchBeanDefinitionException becouse it cannot find beans... what can i do? 我已经在Spring ClassPathXmlApplicationContext中设置了我的类加载器,现在我注意到spring使用我的类加载器加载bean类,但是尽管如此,它仍抛出org.springframework.beans.factory.NoSuchBeanDefinitionException,因为它找不到bean ...我该怎么办? Thanks 谢谢

I see two things that may be worth investigating: 我看到两件值得调查的事情:

  • The code makes the class loader parent-last. 该代码使类加载器的父级最后一位。 There is always a risk that this causes subtle class loading issues. 始终存在导致细微的类加载问题的风险。
  • Maybe it is just the thread context class loader that is not set properly. 可能只是线程上下文类加载器未正确设置。

I'm not very good at class loaders, but from you code it's only possible to assume, that in case your class loader can't find a class, it will redirect to system class loader. 我不是很擅长类加载器,但是从您的代码中只能假设,如果您的类加载器找不到类,它将重定向到系统类加载器。 It may work fine when you run application standalone, like in your sample, but if it's a web application that is run on application server it will fail. 当您像示例中那样独立运行应用程序时,它可能会正常工作,但是如果它是在应用程序服务器上运行的Web应用程序,则它将失败。

Application servers usually create a big hierarchy of class loaders and has a separate class loader used to load your application classes. 应用程序服务器通常会创建大型的类加载器层次结构,并具有用于加载应用程序类的单独的类加载器。 In this case, system class loader knows nothing about your Spring related classes and thus can't load them. 在这种情况下,系统类加载器对您的Spring相关类一无所知,因此无法加载它们。

You must keep in mind, that same class may be loaded by several class loaders and if you try to compare same class from different class loaders it will fail. 您必须牢记,同一类可能由多个类加载器加载,并且如果您尝试比较不同类加载器中的同一类,则它将失败。

In your case I would set parent class loader in MyClassLoader constructor. 在您的情况下,我将在MyClassLoader构造函数中设置父类加载器。 As a parent class loader you can use MyClassLoader.class.getClassLoader() I think. 作为父类加载器,您可以使用MyClassLoader.class.getClassLoader()。

public class MyClassLoader extends ClassLoader
{
    public MyClassLoader()
    {
       super(MyClassLoader.class.getClassLoader());
    }

    // other code
}

Hope this may help :) 希望这会有所帮助:)

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

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