Java-在JVM中修改Object类的toString()

时间:2018-08-06 09:05:21

标签: java tomcat proxy mockito javassist

在JVM中,我想更改Object类的toString方法的行为以返回 getClass().getName(); 而不是 getClass().getName() + "@" + Integer.toHexString(hashCode());

我尝试了Javassist的Hotswapper,但是在启动tomcat服务器时需要分配调试端口。还有其他方法可以更改JVM中Object类的toString()的功能吗?

我的用例:我的JVM中的某些对象没有toString()实现。因此,采用Object.class中的基本实现,该实现将不是唯一的(由于哈希码)。我有一个记录和测试环境,在该环境中,值必须是唯一的,然后才可以 自动比较。

1 个答案:

答案 0 :(得分:6)

您可能 可以通过篡改实际的Object.class文件(编译自己的版本,然后将其替换为相应的JAR文件中的.class文件)来做到这一点。但是我非常希望JVM注意到这一点,并为您鼓掌。

在JVM启动之后“完全”执行此操作是完全不可能的。 java.lang类全部由初始的“引导”类加载器加载,该加载器被烘焙到JVM中,并且您无法更改(直到开始构建自己的JVM)。因此,很长在JVM调用您的任何代码之前,它已经加载了java.lang.Object以及它在文件系统中找到的.class文件中的实现。

正如评论所暗示的那样,真正的答案是:你走错了兔子洞。

可能有数百个内部API或第三方库,如果不是成千上万,它们会假定默认的toString()结果看起来像它。当然,依靠这个假设是一个坏主意,但是尽管如此,您的更改可能会破坏此类代码。

除此之外,真正的答案是:当您不喜欢默认行为时,请对您认为重要的类进行更改。

更新1,采用另一种(理论上的)方法:可以挂接到类加载器,以便在加载特定的“用户类”时,将拦截该过程,并添加一个生成的toString()方法(可能是OP尝试使用javaasist进行的操作)。但是OP想要在tomcat上下文中执行此操作,并且tomcat具有自己的复杂的类加载器层次结构。此选项也没有现实的机会!即使您可以完全控制类加载器,我们在这里也正在讨论“黑魔法伏都教”风格的黑客攻击。您为教育项目所做的事情,而不是为在现实世界中必须强大且可靠地运行的事情所做的事情。

更新2,有关更新的要求。 OP基本上希望更改类的特定行为,而无需重新编译它们。但是考虑到 other 的要求,在这里根本不可能做到这一点。在Java中启用此类“动力学”的所有选项均不适合实际的生产环境。

因此,答案始终没有改变:OP的要求在理论上可能是可行的,但就所有实际目的而言,这是不可行的。