如何使URLClassLoader像这样表现? [英] How can I make a URLClassLoader behave like this?

查看:86
本文介绍了如何使URLClassLoader像这样表现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个行为如下的URLClassLoader:

I'm trying to make a URLClassLoader which behaves as follows:



  • 如果要求输入名称为在给定的一组包含物中,将其加载为正常的


  • 否则,返回虚拟类

我无法使用它。在下面的尝试中,我希望 SpecialClassLoader 成功加载 Test $ Thing 。这样,我希望它尝试加载 Test $ SuperThing ,并且我希望它对虚拟类 Nothing 。

I can't get this to work. In the attempt below, I expect the SpecialClassLoader to load Test$Thing succesfully. In doing so, I expect it to attempt to load Test$SuperThing, and I expect it to be okay about the fact that the dummy class Nothing is loaded instead.

但是,出现了一些问题,并抛出了 NoClassDefFoundError 寻找 Test $ SuperThing

However, something goes awry and a NoClassDefFoundError is thrown looking for Test$SuperThing.

有人知道如何解决此问题吗?

Does anyone know how to fix this?

public class Test {

    private static class SuperThing {}

    private static class Thing extends SuperThing {}

    public static void main(String[] args) {
        Set<String> inclusions = new HashSet<String>();
        inclusions.add("Test$Thing"); // note Test$SuperThing is excluded
        URLClassLoader cl = (URLClassLoader) 
            Thread.currentThread().getContextClassLoader();
        SpecialClassLoader cll = 
            new SpecialClassLoader(cl.getURLs(), inclusions);
        try {
            cll.loadClass("Test$Thing"); // line 22 (see stacktrace below)
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static class Nothing {}

    private static final class SpecialClassLoader extends URLClassLoader {

        private final Set<String> inclusions;

            public SpecialClassLoader(URL[] urls, Set<String> inclusions) {
                super(urls);
                this.inclusions = inclusions;
            }

        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (inclusions.contains(name)) {
                return findClass(name); // line 40 (see stacktrace below)
            }
            return Nothing.class;
        }
    }
}

编辑:这是堆栈跟踪我得到了(行号22和40在上面的列表中显示):

here is the stacktrace I get (line numbers 22 and 40 are indicated in listing above):



    Exception in thread "main" java.lang.NoClassDefFoundError: Test$SuperThing
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at Test$SpecialClassLoader.loadClass(Test.java:40)
        at Test.main(Test.java:22)


推荐答案

这是正在发生的事情。

Here is what is happening.


  • 当您尝试加载Test $ Thing时,defineClass方法指出需要加载Test $ Thing的超类;即Test $ SuperThing。

  • When you attempt to load Test$Thing, the defineClass method figures out that it needs to load the superclass of Test$Thing; i.e. Test$SuperThing.

系统类加载器调用您的类加载器,该类加载器返回Nothing类。

The system classloader calls your classloader, which returns the Nothing class.

系统类加载器说糟糕!该类没有正确的完全合格的类名!,并抛出 NoClassDefFoundError

The system class loader says "Woah! that class doesn't have the right fully-qualified classname!!", and throws NoClassDefFoundError.

基本上,此系统类加载器可防止破坏JVM的性能。如果允许自定义类加载器加载错误的类,则可能会发生令人讨厌的事情。例如,考虑一下,如果您在诱使类加载器加载Nothing类之后,某些代码调用了为Test $ SuperThing类定义的某些方法,将会发生什么情况。

Basically, this system classloader is protecting against things that would destabilize the JVM. If it allowed a custom classloader to load the wrong class, nasty things could happen. For example, think about what might happen if some code invoked some method defined for the Test$SuperThing class after you had tricked classloader into loading the Nothing class.

要执行替换某些类的虚拟版本的肮脏技巧,您将需要使用正确的完全限定的类名,正确的超类和接口以及具有正确签名的方法来动态生成字节码。简而言之,您必须满足二进制兼容性规则。否则,无论您尝试在自定义类加载器中尝试执行什么操作,系统类加载器都将拒绝加载类。

If you want to do dirty tricks that substitute a dummy version of some class, you will need to generate bytecode on the fly, using the right fully qualified class name, the right superclass and interfaces, and methods with the right signatures. In short, you must satisfy the binary compatibility rules. If you don't, the system classloader will refuse to load your class ... no matter what you try to do in your custom classloader.

坦白说,您应该对您要尝试执行的操作采取完全不同的方法。

Frankly, you should be taking a completely different approach to whatever it is you are trying to do.

这篇关于如何使URLClassLoader像这样表现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆