【问题标题】:Java - Modify toString() of Object class in JVMJava - 修改 JVM 中 Object 类的 toString()
【发布时间】:2018-08-06 09:05:21
【问题描述】:

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

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

我的用例:我的 JVM 中的一些对象没有 toString() 实现。所以采用 Object.class 中的基本实现,这不会是唯一的(因为哈希码)。我有一个记录和测试环境,其中值需要是唯一的,只有这样它们才能 自动比较。

【问题讨论】:

  • 在 Java 中修改所有类的行为对我来说听起来是个非常糟糕的主意。
  • 你的问题被标记为 [mockito],这让我觉得你可能正在做测试。你能解释一下你为什么要这样做吗?听起来像是 XY 问题。
  • 听起来像是对OOP的误解……
  • 为什么要改变 Object 类的行为。
  • 我的 JVM 中的一些对象没有 toString() 实现。采用 Object.class 中的 SO 基本实现,这不会是唯一的(哈希码的 bcaz)。我有一个记录和测试环境,其中值需要是唯一的,然后才能自动比较它们

标签: java tomcat proxy mockito javassist


【解决方案1】:

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

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

正如 cmets 所暗示的,这里的真正答案是:你走错了兔子洞。

可能有数百个(如果不是数千个)内部 API 或第 3 方库假设默认toString() 结果看起来确实如此。当然,依赖这种假设是一个坏主意,但尽管如此,您的更改可能会破坏此类代码。

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

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

更新 2,关于更新的要求。 OP 基本上想要更改类的特定行为而不重新编译它们。但是考虑到其他的要求,这里根本不可能。在 Java 中启用这种“动态”的所有选项适合真实世界的生产环境。

因此,答案只是简单地保留:OP 要求的内容在理论上可能是可行的,但出于所有实际目的,这是不可行的。

【讨论】:

  • 我已经尝试使用 JavaAssist HotSwapperAgent 来交换类加载器中加载的类,并且它工作成功。让我检查一下我所做的事情的可行性并更新您。感谢您分享您的知识。这只是在测试环境中的一次尝试。
猜你喜欢
  • 2010-10-05
  • 1970-01-01
  • 2015-02-26
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 2018-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多