注:本系列文章均摘录自《深入理解Java虚拟机:JVM高级特性与最佳实践》,作者周志明,我看的是第一版,现在第二版已经出了,
1.在高性能的硬件上部署程序的两种主要方式:
(1)通过64位JDK来使用大内存
(2)使用若干个32位虚拟机简历逻辑集群来利用硬件资源
2.除了Java堆和永久代之外,以下区域还会占用较多内存,这里所有的内存总和会受到操作系统进程最大内存的限制
(1)Direct Memory:可以通过-XX:MaxDirectMemorySize调整大小,内存不足时抛出OutMemoryError或OutOfMemory:Direct buffer memory
(2)线程堆栈:可通过-Xss调整大小,内存不足时抛出StackOverflowError(纵向无法分配,即无法分配新的栈帧)或OutOfMemoryError:uable to create new native thread(横向无法分配,即无法建立新的线程)
(3)Scoket缓存区:每个Socket连接都有Receive和Send两个缓存区,分别占大约37KB和25KB的内存,如果连接多的话,这块内存的占用也比较多,如果无法分配,则可能会抛出IOException:Too many open file异常。
(4)JNI代码:如果代码中使用JNI调用本地库,那本地库使用的内存也不在堆中。
(5)虚拟机和GC:虚拟机和GC的代码执行也要消耗一定的内存。
3.编译时间是指虚拟机的JIT编译器(Just In Time Compiler)编译热点代码(Hot Spot Code)的耗时。为了解决程序解释执行速度的问题,JDK1.2以后,虚拟机内置了两个运行时编译器,如果一段Java代码的调用次数到达一定程度,就会被判定为热代码,从而交给JIT编译器即时编译为本地代码,以提高运行速度(这就是HotSpot虚拟机名字的由来)。Java运行期编译的最大缺点就是编译需要消耗程序正常的运行时间,也就是”编译时间“。
虚拟机提供了一个参数-Xint禁止编译运作,强制虚拟机堆字节码采用纯解释方式执行。
当虚拟机运行在-client模式的时候,使用的是一个代号为C1的轻量级编译器,另外还有一个代号为C2的相对重量级的编译器,它能够提供更多的优化措施。
可以通过以下几个参数要求虚拟机生成GC日志:-XX:+PrintGCTimeStamps(打印GC停顿时间)、-XX:+PrintGCDetails(打印GC详细信息)、-verbose:gc(打印GC信息,输出内容已经被前一个参数包括,可以不写)、-Xloggc:gc.log。
可以把-Xms和-XX:PermSize参数值分别设置为-Xmx和-XX:MaxPermSize参数值,强制虚拟机在启动的时候就把老年代和永久代的容量固定下来,避免运行时自动扩展。
在vm参数-XX:+DisableExplicitGC屏蔽掉System.gc();