总览

Java中最常见的陷阱之一就是知道如何打印数组。 如果有关如何打印阵列的答案获得了超过1000票赞成票,那么您必须怀疑是否有更简单的方法。 几乎所有其他流行语言都具有这种更简单的方法,因此我不清楚Java为什么仍会这样做。

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

它打印类型和地址吗?

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

看起来没有什么变化?

如果我运行以下程序。

public class ObjectTest {boolean[] booleans = {true, false};byte[] bytes = {1, 2, 3};char[] chars = "Hello World".toCharArray();short[] shorts = {111, 222, 333};float[] floats = {1.0f, 2.2f, 3.33f, 44.44f, 55.555f, 666.666f};int[] ints = {1, 22, 333, 4_444, 55_555, 666_666};double[] doubles = {Math.PI, Math.E};long[] longs = {System.currentTimeMillis(), System.nanoTime()};String[] words = "The quick brown fox jumps over the lazy dog".split(" ");@Testpublic void testToString() throws IllegalAccessException {Map<String, Object> arrays = new LinkedHashMap<>();for(Field f : getClass().getDeclaredFields())arrays.put(f.getName(), f.get(this));arrays.entrySet().forEach(System.out::println);}
}

它打印。

booleans=[Z@277c0f21
bytes=[B@6073f712
chars=[C@43556938
shorts=[S@3d04a311
floats=[F@7a46a697
ints=[I@5f205aa
doubles=[D@6d86b085
longs=[J@75828a0f
words=[Ljava.lang.String;@3abfe836

我认为这对每个人都是显而易见的。 O_O喜欢的事实,J是一个翁内部码和L为的J ava类的内部码。 当b未使用时, Z也是布尔值的代码。

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

在此程序中,我们最终不得不编写一个特殊的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中,我们可以通过添加到命令行将此类添加到bootclasspath的开头

-Xbootclasspath/p:target/classes

(或您的类已编译到的任何位置),现在当我们运行程序时,

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,以便为数组生成合理的输出。 它知道您需要一个并提供它,但是将其隐藏在您必须通过Google查找的类中,以便每个新的Java开发人员在第一次尝试使用数组时都必须拥有一个WTF时刻。

翻译自: https://www.javacodegeeks.com/2016/03/printing-arrays-hacking-jvm.html

通过入侵JVM打印阵列相关推荐

  1. jvm 宕机 打印jvm_通过入侵JVM打印阵列

    jvm 宕机 打印jvm 总览 Java中最常见的陷阱之一就是知道如何打印数组. 如果有关如何打印阵列的答案获得了超过1000票赞成票,那么您必须怀疑是否有更简单的方法. 几乎所有其他流行语言都具有这 ...

  2. 入侵JVM?Java Agent原理浅析和实践(上)

    声明:本文首发于京东零售技术公众号,为博主本人撰写投稿. 前言: 在平时的开发中,我们不可避免的会使用到Debug工具,JVM作为一个单独的进程,我们使用的Debug工具可以获取JVM运行时的相关的信 ...

  3. JVM实用参数(三)打印所有XX参数及值

    原文地址:https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-3-printing-all-xx-flags-and-their- ...

  4. 打印JVM所有参数列表的方法 -XX:PrintFlagsFinal、–XX:PrintCommandLineFlags

    1.–XX:PrintFlagsFinal 在JVM启动后,在命令行中输入命令java –XX:+PrintFlagsFinal -version可以输出按字母排序的所有XX参数和值的表格. 注:不同 ...

  5. 该使用哪些工具来诊断和修复 JVM 内存调试的问题?

    这是我有关JVM内存管理和调试的系列文章的第2部分. 在这里阅读第1部分: JVM内存管理和故障排除入门-1 在这篇文章中,我们将讨论基于jvm的应用程序的内存问题的症状,我们可以使用哪些工具来诊断它 ...

  6. 打印Java数组的最简单方法是什么?

    在Java中,数组不会覆盖toString() ,因此,如果尝试直接打印一个,则将得到className +'@'+数组的hashCode的十六进制,如Object.toString()所定义: in ...

  7. 追踪JVM中的本地内存

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 转载自公众号:锅外的大佬 1.概述 有没有想过为什么Java应用程序通过众所周知的-Xms和 ...

  8. JVM基础(6)-常用参数总结

    参考文章: 并发编程网:http://ifeve.com/useful-jvm-flags-part-4-heap-tuning/ 一.参数分类 HotSpot JVM 提供了三类参数. 第一类包括了 ...

  9. 小师妹学JVM之:JVM中的Safepoints

    文章目录 简介 GC的垃圾回收器 分代回收器中的问题 safepoints safepoint一般用在什么地方 总结 简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标 ...

最新文章

  1. 王兴和张一鸣和我们的互联网启蒙
  2. 关于REID的mAP指标
  3. UVa 242 邮票和信封(完全背包)
  4. 【Python学习系列三】Windows下Python第三方常用库安装
  5. 成功解决Exception “unhandled ImportError“cannot import name ‘imread‘ from ‘scipy.misc‘
  6. leetcode 小青蛙跳梯子
  7. [Swift]loadNibNamed方法
  8. LeetCode 764. 最大加号标志(DP)
  9. redis 分布式锁的 5个坑,真是又大又深
  10. java怎么自增2_从头认识java-2.3 自增自减与关系操作符
  11. Windows 命令行改主机名、加域、退域、更改IP
  12. VBS 访问WMI读取IP地址,并将其设置为静态IP
  13. mysql的collate_MYSQL中的COLLATE是什么?
  14. linux系统notebook,Linux下配置jupyter-notebook
  15. 读书笔记_算法第四版(一)
  16. AD10封装库转到PADS封装库里
  17. 屏幕录制(Giphy Capture)并导出Gif动图
  18. Lua-面试考题附答案解析(一)
  19. css平行四边形与菱形变换
  20. Kafka拉取某一个时间段內的消息

热门文章

  1. 厉害了,Servlet3的异步处理机制
  2. 《此生未完成》痛句摘抄(3)
  3. mybatis简单案例源码详细【注释全面】——Dao层映射文件(UserMapper.xml)【重要】
  4. p2p linux 开源项目,权威开源项目(linux系统、sip、live555)
  5. 学生上课睡觉班主任怎么处理_【师问师答】学生上课说话,点名批评还嘴怎么办?...
  6. 服务器io修改,更改 Linux I/O 调度器来改善服务器性能
  7. diy实现spring依赖注入
  8. eclipse maven 项目发布到tomcat 报错 Failed to scan JAR [file:/C:/xxxxx.jar] from WEB-INF/lib
  9. http响应状态码列表
  10. ROC和AUC介绍以及如何计算AUC