Java类加载器:如何加载具有与查找名称不同的二进制名称的类?

时间:2015-01-13 23:29:36

标签: java jvm classloader

编辑:似乎有些不同,请先阅读Edit2。

如何加载具有与查找名称不同的二进制名称的类?

我知道Java规范不允许这样做,但我面前有一个应用程序以某种方式完成它。

我有一个专有的服务器(运行JVM的Windows exe),创建它的公司不再存在。自从我最终遇到一个错误后,我开始提取类来修复它并同时将其移动到Linux。这些课程是混淆的,但这并不困扰我。

我操纵他们的顶级类加载器在调用defineClass后转储每个类文件(它从加密存档中加载类)。在那里我看到它查找并定义了一个类P.x但是转储的类文件包含一个二进制名称为P.X的类(不匹配)(还有一些名为P.X $ Y的内部类,因此它们匹配二进制名称)。案例不匹配应在NoClassDefFoundError中抛出defineClass(),但由于我在defineClass()之后直接转储该类,因此它显然没有。

在我理解之前,我有点害怕继续。因为它们可能包含一些陷阱,比如以后必须加载和检查的类。因此,如果我继续而不详细了解其工作原理,服务器可能会返回错误的结果。

从他们打包JVM的方式来看,我认为他们没有操纵JVM。从查看OpenJDK代码这样的东西是在C ++部分,所以他们不能只是替换一些类文件来实现它。

我只能想到3种不破解JVM的方法:

  1. 我希望它可能是一些秘密的VM arg,但到目前为止我什么都没找到:https://web.archive.org/web/20100130070337/http://www.md.pp.ru/~eu/jdk6options.html
  2. 替换java.lang.ClassLoader并将传入的名称设置为null 这样只有二进制名才重要。但这会起作用吗?
  3. 以某种方式使用ClassFileTransformer。但这会起作用吗?
  4. 我没有发现他们做的线索2)或3)。而且我不知道这些是如何工作的,因为代码会查找P.x,所以即使P.X会被加载,所以不确定这些会有用。

    有人知道如何做到这一点吗?他们在Windows上使用32位JRE Hotspot 1.6.0_01-b06混合模式。

    法律声明:在我的国家,我明显被允许修复我付了很多钱并且不再受支持的软件。

    EDIT1:
    我现在将我的小样本注入其代码中。它以NoClassDefFoundError失败,因此它们不会操纵JVM或java.lang.ClassLoader,因此不会在全局范围内完成此测试。

    EDIT2:
    它可能是文件系统,但是在评论中建议的另一种方式(我覆盖文件) 由于我现在可以附加一个调试器,我看到了一些奇怪的东西:进入byte[]的{​​{1}}包含正确的二进制名称。
    如果存在P / x和P / X,我会覆盖一个,因为Windows FS不区分大小写。卫生署。如果我确定是这样的话会回来的。

2 个答案:

答案 0 :(得分:1)

也许他们绕过了正常的Classloader#defineClass实现并改为使用sun.misc.Unsafe#defineClass

答案 1 :(得分:0)

问题是Windows文件系统不区分大小写(但不是因为加载了类似注释中建议的类,而是因为我编写了文件转储)。

我用他们的名字写出了这些类,但由于P.x和P.X存在,我确实用P.X覆盖了P.x.

所以它只是在寻找我,好像是从文件P.x加载P.X,因为在我的转储文件中,由于该错误,P.x是P.X类。

谢谢大家,抱歉。