性能文章>【译】打印数组的最难得的一种实现方式:侵入JVM>

【译】打印数组的最难得的一种实现方式:侵入JVM转载

1年前
258127

Java 中有个讨论最多的问题,那就是打印数组的办法是什么?几乎所有其他流行语言都有比较简单的方法,但是不清楚为什么 Java 仍然用侵入JVM的方式。

与其他 JDK 类不同,数组没有特别健全的 toString(),因为它继承自 Object。

它打印的类型和地址对吗?

实际上,它不会打印地址,它看起来就像一个神秘的一样。它打印类型的内部表示,以及对象的hashCode()。由于所有数组都是一个对象,它们有一个 hashCode() 和一个类型和一个同步锁,以及一个对象所具有的所有其他东西,但没有特定于数组的方法。这就是 toString() 对数组没有用的原因。

它看起来好像没实现?

如果我运行以下程序。

prints:

显而易见,就像 J 是 long 的内部代码 ,L是 Java 类的内部代码一样。当b 未使用时, 也是布尔值的代码 。

我们对于它可以做些什么呢?

在这个程序中,我们最终不得不为对象编写一个特殊的 toString 方法,该方法需要由我们用于打印 Map.Entry 的特殊方法调用。重复此多次以提高程序的吞吐量,避免在 Java 中使用数组更容易,因为它们很难调试。

侵入 JVM 到底如何?

我们可以做的是改变 Object.toString()。我们必须更改此类,因为它是我们可以访问的数组的唯一父级。我们无法更改数组的代码,因为它在 JVM 内部。例如,对于所有 byte[] 特定方法,没有 byte[] java 类文件。

获取 java.lang.Object 源的副本并将 toString() 替换为

public String toString() {

        if (this instanceof boolean[])

            return Arrays.toString((boolean[]) this);

        if (this instanceof byte[])

            return Arrays.toString((byte[]) this);

        if (this instanceof short[])

            return Arrays.toString((short[]) this);

        if (this instanceof char[])

            return Arrays.toString((char[]) this);

        if (this instanceof int[])

            return Arrays.toString((int[]) this);

        if (this instanceof long[])

            return Arrays.toString((long[]) this);

        if (this instanceof float[])

            return Arrays.toString((float[]) this);

        if (this instanceof double[])
           
           return Arrays.toString((double[]) this);

        if (this instanceof Object[])

            return Arrays.deepToString((Object[]) this);

        return getClass().getName() + "@" + Integer.toHexString(hashCode());

    }

在 Java <= 8 中,我们可以通过添加到命令行将此类添加到引导类路径的开头

 

(或者你的类被编译到的任何地方)现在当我们运行我们的程序时,我们看到

booleans=[true, false]

bytes=[1, 2, 3]

chars=[H, e, l, l, o,  , W, o, r, l, d]

shorts=[111, 222, 333]

floats=[1.0, 2.2, 3.33, 44.44, 55.555, 666.666]

ints=[1, 22, 333, 4444, 55555, 666666]

doubles=[3.141592653589793, 2.718281828459045]

longs=[1457629893500, 1707696453284240]

words=[The, quick, brown, fox, jumps, over, the, lazy, dog]

就像你用任何其他语言一样。

结论

虽然这是一个很酷的技巧,但最好的解决方案当然是他去修复Java,以便它为数组生成一个健全的输出。

它知道你需要一个并提供它,但将它隐藏在一个你必须用谷歌搜索的类中,所以每个新的 Java 开发人员在他们第一次尝试使用数组时都必须有一个 WTF 时刻。

原文地址:https://dzone.com/articles/printing-arrays-by-hacking-the-jvm

原文作者:Peter Lawrey/DeveloperVanilla Java,伦敦

点赞收藏
分类:标签:
willberthos

keep foolish!

请先登录,查看2条精彩评论吧
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

一次 GDB 源码角度分析 jvm 无响应问题

一次 GDB 源码角度分析 jvm 无响应问题

日常Bug排查-集群逐步失去响应

日常Bug排查-集群逐步失去响应

浅析AbstractQueuedSynchronizer

浅析AbstractQueuedSynchronizer

7
2