和你问的不一样,我觉得软件工程主要是用来解决问题的。有博主认为“每个孩子都应该学习编程”,“你以为数学只是为了好玩?如果你看过我的HTML5调试器,你会发现我是一名程序员,但我所做的工作远不只是数学。”“以上都同意一点,软件工程不仅仅是用计算机语言写的一些文字。软件解决的问题定义了程序员的价值。解决问题的最终进步来自于科学,它可以增强我们清晰的头脑和我们一路使用的工具。你注意过那些JDK安装自带的工具吗?既然那些大牛同意把那些工具加入到JDK中,那应该是有用的。因此,在这篇文章中,我挑选了几个标准安装Hotspot后可用的小工具来介绍一下。我们决定忽略那些与安全相关的各种远程方法调用(RMI)、applet、web-start、web-services工具。让我们关注那些普通开发人员在开发常见应用程序时可能会觉得有用的工具。注意,如果你只对命令行工具感兴趣,而不仅仅是Java相关工具,这里有5个非常有用的命令行工具。同样,以下并不是JDK工具的完整列表,但我们希望为您提供一个精简版。以下是您可以使用这些命令执行的一些非常有用的操作。0.javap您可以将这些有用的参数传递给javap(Java类文件反编译器):-I-打印行号和局部变量-p-打印所有类和成员信息,包括非公开的,-c-打印方法字节码例如,在著名的《你真的了解Classloader吗?speech,当出现NoSuchMethodException错误时,我们可以执行以下命令来调查这个类有哪些成员方法,并获得我们在这个类中寻找的所有信息:javap-l-c-pUtil2javap在调试类内部时很有用或调查随机字节码排序。1.jjsjjs命令可以启动一个JavaScript命令终端,你可以把它当作一个计算器使用,或者用随机的JS字符串来测试JS的怪异用法。不要让另一个JavaScript谜题让您措手不及!哈,看看刚刚发生了什么?但是JavaScript是另一个话题,只要知道即使没有node.js或浏览器也可以使用jjs来了解JS是如何工作的。2、jhatJava堆分析工具(jhat)顾名思义:分析转储堆信息。在下面的小例子中,我们构造了一个OutOfMemoryError,然后给java进程指定-XX:+HeapDumpOnOutOfMemoryError,这样运行时就会生成一个dump文件供我们分析。publicclassOhMyMemory{privatestaticMapmap=newHashMap<>();publicstaticvoidmain(String[]args){Runtime.getRuntime().addShutdownHook(newThread(){@Overridepublicvoidrun(){System.out.println("Wehaveaccumulated"+map.size()+"entries");}});for(inti=0;;i++){map.put(Integer.toBinaryString(i),i);}}}生成OutOfMemoryError很简单(在大多数情况下我们不打算为此),我们只需要继续制作阻止垃圾收集器工作的东西。运行此代码会产生以下输出:org.shelajev.throwaway.jdktools.OhMyMemoryjava.lang.OutOfMemoryError:JavaheapspaceDumpingheaptojava_pid5644.hprof...Heapdumpfilecreated[73169721bytesin0.645secs]Exceptioninthread"main"java.MapheilapashErrorat:.resize(HashMap.java:703))atjava.util.HashMap.putVal(HashMap.java:662)atjava.util.HashMap.put(HashMap.java:611)atorg.shelajev.throwaway.jdktools.OhMyMemory.main(OhMyMemory.java:24)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)atjava.langodthreflect.invoke.injava:483..rt.execution.application.AppMain.main(AppMain.java:134)我们已经积累了393217个条目很好,我们现在有一个文件可供分析。我们对这个文件执行jhat开始分析,jhat会分析这个文件并打开一个http服务器供我们查看结果。$jhatjava_pid5644.hprofReadingfromjava_pid5644.hprof...DumpfilecreatedThuAug1414:48:19EEST2014Snapshotread,resolving...Resolving1581103objects...Chasingreferences,expect316dots...Eliminatingduplicatereferences.........Snapshotresolved.StartedHTTPserveronport7.000serverisreadyhttpserveronport7.000serverisready已解决:7000查看转储数据。在该页面上,我们可以通过堆信息的直方图看到内存不足的情况。现在我们可以清楚的看到,这个拥有393567个节点的HashMap是导致程序崩溃的罪魁祸首。虽然有更多工具可以检查内存分配使用情况和堆分析,但内置了jhat并且是分析的良好开端。3.jmapjmap是一个内存映射工具,它提供了另一种获取堆转储文件而不会导致OutOfMemoryErrors的方法。我们把上面的程序稍微修改一下看看效果。publicclassOhMyMemory{privatestaticMapmap=newHashMap<>();publicstaticvoidmain(String[]args){Runtime.getRuntime().addShutdownHook(newThread(){@Overridepublicvoidrun(){try{System.out.println("Entersomething,soI'llreleasetheprocess");System.in.read();System.out.println("Wehaveaccumulated"+map.size()+"entries");}catch(IOExceptione){e.printStackTrace();}}});for(inti=0;i<10000;i++){map.put(Integer.toBinaryString(i),i);}}}注意现在我们不想消耗大量内存,早点结束就好了在进程关闭挂钩中等待不要让JVM退出。这允许我们使用jmap连接到进程以获取宝贵的内存转储。所以可以使用jmap的两个函数来实现,获取heap统计信息和触发heapdump。因此,执行时:jmap-heap1354(这里的1354是上面程序的进程号),可以得到一个很好的内存使用统计信息:$jmap-heap1354AttachingtoprocessID1354,pleasewait...Debuggerattachedsuccessfully.Servercompilerdetected.JVMversionis25.0-b70usingthread-localobjectallocation.ParallelGCwith4thread(s)HeapConfiguration:MinHeapFreeRatio=40MaxHeapFreeRatio=70MaxHeapSize=67108864(64.0MB)NewSize=1572864(1.5MB)MaxNewSize=22020096(21.0MB)OldSize=45088768(43.0MB)NewRatio=2SurvivorRatio=8MetaspaceSize=21807104(20.796875MB)CompressedClassSpaceSize=1073741824(1024.0MB)MaxMetaspaceSize=17592186044415MBG1HeapRegionSize=0(0.0MB)HeapUsage:PSYoungGenerationEdenSpace:capacity=1048576(1.0MB)used=628184(0.5990829467773438MB)free=420392(0.40091705322265625MB)59.908294677734375%usedFromSpace:capacity=524288(0.5MB)已用=491568(0.4687957763671875MB)免费=32720(0.0312042236328125MB)93.7591552734375%已用空间:容量=524288(0.5MB)已用=0(0.0MB)免费=524MBSO已用)0.5%ncapacity=45088768(43.0MB)使用=884736(0.84375MB)free=44204032(42.15625MB)1.9622093023255813%used981internedStringsoccupying64824bytes.$jmap-dump:live,format=b,file=heap.bin1354Dumpingheapto/Users/shelajev/workspace_idea/throwaway/throwaway/heapdumpfiletrigger也可以...当前的堆转储可以在以后随意分析。您可以将-dump参数传递给jmap,如下例所示。现在有了dump得到的heap.bin文件,接下来就可以使用自己喜欢的内存分析工具来分析了。4、jpsjps是最常用的显示Java程序系统进程(PID)的工具。它与平台无关并且非常易于使用。想象一下,我们启动上面的程序并想用jmap连接到它。这时候我们就需要程序的PID,jps正好派上用场。$jps-mlv5911com.intellij.rt.execution.application.AppMainorg.shelajev.throwaway.jdktools.OhMyMemory-Xmx64m-Didea.launcher.port=7535-Didea.launcher.bin.path=/Applications/IntelliJIDEA14EAP.app/Contents/bin-Dfile.encoding=UTF-85544-Dfile.encoding=UTF-8-ea-Dsun.io.useCanonCaches=false-Djava.net.preferIPv4Stack=true-Djsse.enableSNIExtension=false-XX:+UseConcMarkSweepGC-XX:SoftRefLRUPolicyMSPerMB=50-XX:+HeapDumpOnOutOfMemoryError-Xverify:none-Xbootclasspath/a:../lib/boot.jar-Xms128m-Xmx750m-XX:MaxPermSize=350m-XX:ReservedCodeCacheSize=225m-XX:+UseCompressedOops-agentlib:yjpagent=probe_disable=*,disablealloc,disabletracing,onlylocal,disableexceptiontelemetry,delay=10000,sessionname=IntelliJIdea14-Didea.java.redist=NoJavaDistribution-Didea.home.path=/Applications/IntelliJIDEA14EAP.app/Contents-Didea.paths.selector=IntelliJIdea145930sun.tools.jps.Jps-mlvV-Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home-Xms8m我们发现很多情况下,“-mlv”参数组合***使用它会打印main方法的参数,完整的包名,以及JVM相关参数。这样你就可以在一大堆类似的流程中找到你想要的了。现在你havedump得到的文件heap.bin可以用你喜欢的内存分析工具进行分析5.jstackjstack是一个线程栈工具,生成一个指定的JVM进程,当你的程序一直在那里盘旋,而你想找出什么是thread是在干什么导致死锁的,那么jstack最合适,jstack只有几个参数选项,如果不清楚就全部加上,如果后面发现一些对你没有意义的信息,可以调整参数来限制它的输出。-F选项可以用来强制转储,这在进程挂起时非常有用,-I选项可以打印同步和锁定信息。$jstack-F-l9153AttachingtoprocessID9153,pleasewait...Debuggerattachedsuccessfully.Servercompilerdetected.JVMversionis25.0-b70DeadlockDetection:Nodeadlocksfound...虽然上面的输出看起来很简单,但是里面包含了每个线程的状态和它当前的栈信息。jstack非常好用,我们在日常工作中使用它的频率非常高,尤其是我们负责启动和停止应用服务器的测试引擎。测试工作往往并不顺利,jstack可以让我们知道JVM内部的运行状态,而不会产生任何负面影响。-NeemePraks(高级产品工程师,ZeroTurnaround)还有什么吗?今天我们介绍一下JDK发行版预装的Awesome工具。相信我,总有一天你会用到其中的一些。所以,如果你有时间,你可以去看看他们的官方文档。尝试在不同的场景中使用它们并喜欢它们。如果你想学习一些JDK没有自带的很棒的工具,你可以看看JRebel,它可以让你立即看到代码更改的效果,还有我们的新产品XRebel,它可以像X光一样扫描你的计算机眼镜。网络应用程序。如果您知道对开发最佳实践至关重要的小工具,请在本文末尾发表评论或在Twitter@shelajev上分享此工具的详细信息。奖励部分:参考奖励部分:参考以下是可用JDK工具的更完整列表。虽然这不是完整列表,但为了节省空间,我们省略了加密、网络服务相关工具等。感谢manpagez.com提供的资源。jar—用于创建和管理jar文件的工具。java—Java应用程序启动器。在本文中,启动器用于开发和部署。javac—Java编译器。javadoc—API文档生成器。javah—在本机方法中用于生成C语言头文件和源文件。javap—类文件反编译器。jcmd—JVM命令行诊断工具,可将诊断命令请求发送到JVM。jconsole—用于监控JVM的符合JMX的图形工具。您可以监控本地和远程JVM,也可以监控和管理单个应用程序。jdb—Java调试器。jps—JVM进程查看器,列出了系统上运行的所有热点JVM进程。jstat—JVM状态监控工具。它可以收集并打印指定JVM进程的性能状态。jhat—堆转储信息的浏览器,启动一个网络服务器来显示你获得的堆转储信息,例如jmap-转储。jmap—一种Java内存映射工具,可打印有关指定进程、核心文件、远程调试服务器共享内存映射或堆内存的详细信息。jsadebugd—Java服务调试守护进程—附加到Java进程或核心文件并充当调试服务器。jstack-Java堆栈信息工具-打印指定进程或核心文件或远程调试服务器的线程堆栈。jjs—运行Nashorn命令行脚本shell。jrunscript—Java脚本运行工具。但你必须知道,这实际上是一个尚未支持的测试版功能。它可能会在未来的JDK版本中被删除。希望以上内容对您有所帮助,您可以在推特@shelajev上留下您宝贵的意见。如果您知道我没有提到的一些重要工具,请告诉我。
