通过入侵JVM打印阵列
总览
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打印阵列相关推荐
- jvm 宕机 打印jvm_通过入侵JVM打印阵列
jvm 宕机 打印jvm 总览 Java中最常见的陷阱之一就是知道如何打印数组. 如果有关如何打印阵列的答案获得了超过1000票赞成票,那么您必须怀疑是否有更简单的方法. 几乎所有其他流行语言都具有这 ...
- 入侵JVM?Java Agent原理浅析和实践(上)
声明:本文首发于京东零售技术公众号,为博主本人撰写投稿. 前言: 在平时的开发中,我们不可避免的会使用到Debug工具,JVM作为一个单独的进程,我们使用的Debug工具可以获取JVM运行时的相关的信 ...
- JVM实用参数(三)打印所有XX参数及值
原文地址:https://blog.codecentric.de/en/2012/07/useful-jvm-flags-part-3-printing-all-xx-flags-and-their- ...
- 打印JVM所有参数列表的方法 -XX:PrintFlagsFinal、–XX:PrintCommandLineFlags
1.–XX:PrintFlagsFinal 在JVM启动后,在命令行中输入命令java –XX:+PrintFlagsFinal -version可以输出按字母排序的所有XX参数和值的表格. 注:不同 ...
- 该使用哪些工具来诊断和修复 JVM 内存调试的问题?
这是我有关JVM内存管理和调试的系列文章的第2部分. 在这里阅读第1部分: JVM内存管理和故障排除入门-1 在这篇文章中,我们将讨论基于jvm的应用程序的内存问题的症状,我们可以使用哪些工具来诊断它 ...
- 打印Java数组的最简单方法是什么?
在Java中,数组不会覆盖toString() ,因此,如果尝试直接打印一个,则将得到className +'@'+数组的hashCode的十六进制,如Object.toString()所定义: in ...
- 追踪JVM中的本地内存
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 转载自公众号:锅外的大佬 1.概述 有没有想过为什么Java应用程序通过众所周知的-Xms和 ...
- JVM基础(6)-常用参数总结
参考文章: 并发编程网:http://ifeve.com/useful-jvm-flags-part-4-heap-tuning/ 一.参数分类 HotSpot JVM 提供了三类参数. 第一类包括了 ...
- 小师妹学JVM之:JVM中的Safepoints
文章目录 简介 GC的垃圾回收器 分代回收器中的问题 safepoints safepoint一般用在什么地方 总结 简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标 ...
最新文章
- 王兴和张一鸣和我们的互联网启蒙
- 关于REID的mAP指标
- UVa 242 邮票和信封(完全背包)
- 【Python学习系列三】Windows下Python第三方常用库安装
- 成功解决Exception “unhandled ImportError“cannot import name ‘imread‘ from ‘scipy.misc‘
- leetcode 小青蛙跳梯子
- [Swift]loadNibNamed方法
- LeetCode 764. 最大加号标志(DP)
- redis 分布式锁的 5个坑,真是又大又深
- java怎么自增2_从头认识java-2.3 自增自减与关系操作符
- Windows 命令行改主机名、加域、退域、更改IP
- VBS 访问WMI读取IP地址,并将其设置为静态IP
- mysql的collate_MYSQL中的COLLATE是什么?
- linux系统notebook,Linux下配置jupyter-notebook
- 读书笔记_算法第四版(一)
- AD10封装库转到PADS封装库里
- 屏幕录制(Giphy Capture)并导出Gif动图
- Lua-面试考题附答案解析(一)
- css平行四边形与菱形变换
- Kafka拉取某一个时间段內的消息
热门文章
- 厉害了,Servlet3的异步处理机制
- 《此生未完成》痛句摘抄(3)
- mybatis简单案例源码详细【注释全面】——Dao层映射文件(UserMapper.xml)【重要】
- p2p linux 开源项目,权威开源项目(linux系统、sip、live555)
- 学生上课睡觉班主任怎么处理_【师问师答】学生上课说话,点名批评还嘴怎么办?...
- 服务器io修改,更改 Linux I/O 调度器来改善服务器性能
- diy实现spring依赖注入
- eclipse maven 项目发布到tomcat 报错 Failed to scan JAR [file:/C:/xxxxx.jar] from WEB-INF/lib
- http响应状态码列表
- ROC和AUC介绍以及如何计算AUC