深入理解JVM之内存区域与内存溢出 诊断工具

与你的问题不同,我认为软件工程主要是用来解决问题的。有些博客认为“每个小孩都应该学习编程”,“你认为学数学只是玩玩而已?如果你有看过我的HTML5调试器的话,你会发现我是一个程序员,但我做的工作远不止数学这些”。 上面两者都同意一个观点,软件工程不只是用计算机语言写的一些只言片语。软件解决的问题诠释了程序员的价值。

解决问题的最终进展来自科学、强化清晰的头脑和我们一路以来使用的工具。

推荐普通开发者学习使用的6个JDK内建工具

你有没有留意过那些 JDK 安装附带的工具?既然那些大牛同意把那些工具加到 JDK 里,应该是有用的。

因此,在这篇文章里,我挑了几个 Hotspot 标准安装后可用的小工具来介绍。我们决定忽略那些安全相关的和各种远程方法调用(RMI)、applets、web-start、web-services 工具。让我们把焦点放在那些普通开发者开发一般应用过程中可能有用的工具。注意,如果你只是对命令行工具感兴趣,而不仅仅是Java相关的工具,这里介绍了 5 个非常有用的命令行工具。

再次重申,下面虽然不是 JDK 工具完整列表,但是我们想给你一个精华版本。下面是你用这些命令可以完成的真正有用的事情。

0、javap

你可以给 javap(Java Class文件反编译器)传递这些有用的参数:

  • -I – 打印行数和局部变量
  • -p – 打印包括非public在内的所有类和成员信息,
  • -c – 打印方法字节码

比如在著名的“你真的懂 Classloader 吗?”演讲里,当出现 NoSuchMethodException 错误时,我们可以执行以下命令来调查这个类究竟有哪些成员方法和获取这个类所有想找的信息:

javap -l -c -p Util2

推荐普通开发者学习使用的6个JDK内建工具

当调试类内部信息或者研究随机字节码顺序时,javap 非常有用。

1、jjs

推荐普通开发者学习使用的6个JDK内建工具

jjs命令可以启动一个 JavaScript 命令终端,你可以把它当做计算器或者用随机的JS字符串测试JS的古怪用法。不要让另一个 JavaScript 谜题让你措手不及!

哈,看到刚刚发生了什么了么?但是 JavaScript 是另一个话题,只需要知道即使没有 node.js 或浏览器你也可以用jjs知道JS是怎么工作的。

2、jhat

Java堆分析工具(jhat)正如它名字描述的那样:分析dump堆信息。在下面的小例子里,我们构造了一个 OutOfMemoryError ,然后给这个 java 进程指定 -XX:+HeapDumpOnOutOfMemoryError ,这样运行时就会产生一个 dump 文件供我们分析。

public class OhMyMemory {

 private static Map map = new HashMap<>();

 public static void main(String[] args) {
   Runtime.getRuntime().addShutdownHook(
     new Thread() {
       @Override
       public void run() {
         System.out.println("We have accumulated " + map.size() + " entries");
       }
     }
   );
   for(int i = 0; ;i++) {
     map.put(Integer.toBinaryString(i), i);
   }
 }
}

产生一个 OutOfMemoryError 很简单(大部分情况下我们无意为之),我们只要不断地制造不让垃圾回收器起作用就可以了。

运行这段代码会产生如下输出:

org.shelajev.throwaway.jdktools.OhMyMemory
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid5644.hprof ...
Heap dump file created [73169721 bytes in 0.645 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.resize(HashMap.java:703)
at java.util.HashMap.putVal(HashMap.java:662)
at java.util.HashMap.put(HashMap.java:611)
at org.shelajev.throwaway.jdktools.OhMyMemory.main(OhMyMemory.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
We have accumulated 393217 entries

不错,我们现在有一个可供分析的文件了。我们对这个文件执行jhat开始进行分析,jhat 会分析这个文件开启一个 http 服务器供我们查看结果。

$ jhat java_pid5644.hprof
Reading from java_pid5644.hprof...
Dump file created Thu Aug 14 14:48:19 EEST 2014
Snapshot read, resolving...
Resolving 1581103 objects...
Chasing references, expect 316 dots...
Eliminating duplicate references........
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

可以通过访问 http://localhost:7000 来查看 dump 的数据。

展开阅读全文

没有更多推荐了,返回首页