简体   繁体   English

检测不同ClassLoader加载的类的Class对象等效性

[英]Detecting Class object equivalence for classes loaded by different ClassLoaders

My Task is to write a unit test for a method findSubClassImplementation that returns an instance for a given Class object. 我的任务是为方法findSubClassImplementation编写单元测试,该方法返回给定Class对象的实例。 The method signature looks like this: 方法签名如下所示:

public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception 

Internally the method checks wether the supplied Class object belongs to a set of known classes and then returns an instance of that class: 该方法在内部检查所提供的Class对象是否属于一组已知的类,然后返回该类的实例:

if (Subclass.class.equals(cls)) 
        return (T) new Subclass(args);

If the class is not known, an Exception is thrown. 如果该类未知,则引发Exception。 This code is given 该代码给出

I tried to load all Classes inheriting from SuperClass via Reflection and then pass them as argument to findSubClassImplementation : 我试图通过反射加载从SuperClass类继承的所有类,然后将它们作为参数传递给findSubClassImplementation

Set<Class<? extends SuperClass>> subTypesOf = reflections.getSubTypesOf(SuperClass.class);
Class<? extends SuperClass> clazz = subTypesOf.iterator().next();
SuperClass instance = findSubClassImplementation(clazz);

I then use a Debugger to step into the method, and I can see the line of code where 然后,我使用Debugger进入该方法,然后可以看到以下代码行:

if (Subclass.class.equals(cls)) 

returns false, although cls = Subclass.class 返回错误,尽管cls = Subclass.class

I assume what happens is this: Class does not implement equals, thus equals of Object is used, that compares with "==". 我假设发生了什么: Class未实现equals,因此使用了equals的Object ,与“ ==”进行比较。 As reflection uses a different ClassLoader than is used in findSubClassImplementation the two class Objects are different. 由于反射使用的类加载器不同于findSubClassImplementation使用的类加载器,因此两个类对象是不同的。 Is this assumption correct? 这个假设正确吗?

Is it possible to get the other Class object for a class that I have loaded with Reflection? 是否可以为我已使用反射加载的类获取另一个Class对象? Do you have another idea how to deal with this problem? 您还有其他想法如何处理此问题吗?

ANSWER: 回答:

Turns out I am not very good at reading: The hirarchy is in 3 levels: SuperClass --> IntermediateAbstractClass--> Subclass. 事实证明,我不太擅长阅读:层次结构分为3个级别:超类->中级抽象类->子类。 The comparison is always to the intermediate abstract class: 总是与中间抽象类进行比较:

if (IntermediateAbstractClass.class.equals(cls)) return (T) new Subclass(args);

Thus my question wasn't very accurate or precise - I am sorry if you feel like I wasted your time. 因此,我的问题不是非常准确或精确-如果您觉得我浪费了时间,对不起。 I'll mark Michael Wiles answer as the correct one, because his advice pushed my to discover my missunderstanding. 我将迈克尔·威尔斯的答案标记为正确的答案,因为他的建议促使我发现了我的误会。 Thank you! 谢谢!

Maybe you don't need to check what class is cls , since cls already contains all the information you need. 也许您不需要检查cls是什么类,因为cls已经包含了您需要的所有信息。 Try simply with 简单尝试

public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception {
    // ... retrieve args
    final Class<?>[] constructorParamTypes = new Class<?>[args.length];
    for (int i = 0; i < args.length; i++) {
        constructorParamTypes[i] = args[i].getClass();
    }
    return cls.getConstructor(constructorParamTypes).newInstance(args);
}

Or in the Java 8 way: 或以Java 8方式:

public <T extends SuperClass> T findSubClassImplementation(Class<T> cls) throws Exception {
    // ... retrieve args
    final Class<?>[] constructorParamTypes = Arrays.stream(args).map(Object::getClass)
            .toArray(size -> new Class<?>[size]);
    return cls.getConstructor(constructorParamTypes).newInstance(args);
}

There must be something that is different about the classes... 这些类肯定有一些不同之处...

You say that Subclass.equals(otherSubclass) returns false we need to ascertain why this is the case. 您说Subclass.equals(otherSubclass)返回false,我们需要确定为什么会这样。

Check the name of each class for equality and then check the classloader of each class for equality. 检查每个类的名称是否相等,然后检查每个类的类加载器是否相等。

Based on your provided code to do the reflection there is nothing here to sugggest that these classes loaded by "Reflection" are in fact loaded from different classloaders. 根据您提供的用于执行反射的代码,这里没有任何暗示这实际上是由“反射”加载的这些类是从不同的类加载器加载的。

Furthermore try all sorts of classes, maybe there is something unique about that particular class that causes the behaviour. 此外,尝试各种类型的类,也许该类的某些独特之处会导致这种行为。

One suggestion to try would be to add Integer to the subclass set and then pass in Number to the method... 可以尝试的一种建议是将Integer添加到子类集中,然后将Number传递给该方法...

暂无
暂无

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

相关问题 在Spring Boot和Logback中由不同的Classloader加载的类 - Classes loaded by different Classloaders in Spring Boot and Logback 更改对不同类加载器加载的单例类的影响 - Impact of changes on singleton class loaded by different classloaders 从不同ClassLoader加载的类访问静态方法 - Access static method from classes loaded by different ClassLoaders Spring Data,EclipseLink和SimpleLoadTimeWeaver; 由不同的ClassLoader加载的域类 - Spring Data, EclipseLink, and SimpleLoadTimeWeaver; domain classes loaded by different ClassLoaders 为什么不同自定义类加载器加载的类不能互相调用 - Why the classes loaded by different custom classloaders can't invoke each other 具有多个不同类加载器的单例类 - Singleton class with several different classloaders 如果一个类是由不同的类加载器加载的,那么(sun-jvm)热点优化会发生多次吗? - Does (sun-jvm) hotspot optimization take place multiple times, if a class is loaded by different classloaders? 如何使用两个不同的类加载器加载同一类 - How to load same class with two different classloaders 即使类由类加载器加载,也会发生ClassDefNotFoundException(服务器上安装了多个应用程序) - ClassDefNotFoundException even though the class is loaded by the classloaders (Multiple Applications are installed on the Server) 使用不同的类加载器加载类,以便在不需要时从JVM卸载它们 - loading classes with different classloaders to unload them from the JVM when not needed
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM