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

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

5月前
225815

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!

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

为你推荐

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

【全网首发】一次想不到的 Bootstrap 类加载器带来的 Native 内存泄露分析

记一次“雪花算法”造成的生产事故的排查记录

记一次“雪花算法”造成的生产事故的排查记录

【全网首发】一次疑似 JVM Native 内存泄露的问题分析

【全网首发】一次疑似 JVM Native 内存泄露的问题分析

解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

单服务并发出票实践

单服务并发出票实践

刺激,线程池的一个BUG直接把CPU干到100%了。

刺激,线程池的一个BUG直接把CPU干到100%了。

5
1