JVM运行时数据

1.     结构图

android jvm堆区 栈区 方法区 jvm 堆栈分析_java


2.     Heap

         Java堆是整个JVM共享的,堆的大小取决于配置项(-Xmx-Xms)来指定,堆的最大内存取决于操作系统和硬件环境,比如2G/32位系统,一般也就用800M左右,配多了操作系统会禁止JVM启动的。同时,堆空间并不需要物理上连续的空间,只要逻辑上连续即可。

         堆空间主要分为2个区域,一个叫做Java堆,用于存放各种实例化对象,是垃圾回收机制重点关注的区域,因为对象的申请和释放非常频繁。另一个叫做方法区,又叫非堆,主要用于存放各种被虚拟机加载的信息,如类信息(类名、方法名、属性、接口、版本等)、常量、静态变量、即时编译后的代码等。

    2.1 对象区Heap space

         对象区又称为Java堆,是最大的一块内存,用于存放对象实例,几乎所有的对象都在这里分配内存,是GC重点管理的区域。

        可以通过增加如下配置用于在内存溢出时dump出当前的内存堆转储快照:-XX:+HeapDumpOnOutOfMemoryError


    2.2 方法区PermGen space

        又称为非堆,或者永久区,用于存放类相关信息、常量、静态变量、即时编译后的代码等数据。


3.     Stack

    栈是线程互相独立的,每个线程都有属于自己的栈。

    栈中主要保存运行信息,比如压栈的情况,以及局部变量表,局部变量表的大小,在编译器就已经生成和确定。

    此外,栈可以分为java虚拟机栈和本地方法栈,前者用于存放java的数据,后者用于存放JNI调用情况和数据,在hotspot虚拟机中,二者合二为一,并不做区分。


4.     Direct memory

    直接内存,为NIO服务,是直接向操作系统申请jvm以外的内存,供NIO使用,这些内存不受垃圾回收机制控制

  

5.     关于异常


 

OutOfMemoryError

StackOverFlowError

 

是否存在

出错场景

是否存在

出错场景

程序计数器

×

×

Java虚拟机栈/本地方法栈

栈空间局部变量太多,扩展内存失败

压栈太深,如错误的递归调用

Java堆

实例对象太多,且堆无法扩展

×

 

方法区,包括运行时常量池

加载的类太多,或常量太多,且空间无法扩展

×

 

直接内存

操作系统内存不足

×

 

6.     jvm调优参数

JVM参数配置

1: heapsize

a:-Xmx<n>

指定 jvm 的最大 heap 大小 , 如 :-Xmx=2g

 

b:-Xms<n>

指定 jvm 的最小 heap 大小 , 如 :-Xms=2g , 高并发应用, 建议和-Xmx一样, 防止因为内存收缩/突然增大带来的性能影响。

 

c:-Xmn<n>

指定 jvm 中 NewGeneration 的大小 , 如 :-Xmn256m。这个参数很影响性能,如果你的程序需要比较多的临时内存,建议设置到512M,如果用的少, 尽量降低这个数值, 一般来说128/256足以使用了。

 

d:-XX:PermSize=<n>

指定 jvm 中 PermGeneration 的最小值 , 如 :-XX:PermSize=32m。这个参数需要看你的实际情况,。可以通过jmap 命令看看到底需要多少。

 

e:-XX:MaxPermSize=<n>

指定 Perm Generation 的最大值 , 如:-XX:MaxPermSize=64m

 

f:-Xss<n>

指定线程桟大小 , 如 :-Xss128k, 一般来说,webx框架下的应用需要256K。 如果你的程序有大规模的递归行为,请考虑设置到512K/1M。这个需要全面的测试才能知道。不过,256K已经很大了。这个参数对性能的影响比较大的。

 

g:-XX:NewRatio=<n>

指定 jvm 中 OldGeneration heap size 与 New Generation 的比例 , 在使用 CMS GC 的情况下此参数失效 , 如 :-XX:NewRatio=2

 

h:-XX:SurvivorRatio=<n>

指 定 New Generation 中 Eden Space 与一个 SurvivorSpace 的 heap size 比例 ,-XX:SurvivorRatio=8, 那么在总共 New Generation 为 10m 的情况下 ,EdenSpace 为 8m

 

i:-XX:MinHeapFreeRatio=<n>

指定 jvm heap 在使用率小于 n 的情况下 ,heap 进行收缩,Xmx==Xms 的情况下无效 , 如 :-XX:MinHeapFreeRatio=30

 

j:-XX:MaxHeapFreeRatio=<n>

指定 jvm heap 在使用率大于 n 的情况下 ,heap 进行扩张,Xmx==Xms 的情况下无效 , 如 :-XX:MaxHeapFreeRatio=70

 

k:-XX:LargePageSizeInBytes=<n>

指定 Java heap 的分页页面大小 , 如:-XX:LargePageSizeInBytes=128m

 

2:garbage collector

 

a:-XX:+UseParallelGC

指 定在 New Generation 使用 parallelcollector, 并行收集 , 暂停 app threads, 同时启动多个垃圾回收 thread, 不能和 CMS gc 一起使用 . 系统吨吐量优先 , 但是会有较长长时间的 app pause, 后台系统任务可以使用此 gc

 

b:-XX:ParallelGCThreads=<n>

指定 parallelcollection 时启动的 thread 个数 , 默认是物理 processor 的个数 ,

 

c:-XX:+UseParallelOldGC

指定在 Old Generation 使用 parallelcollector

 

d:-XX:+UseParNewGC

指定在 New Generation 使用 parallelcollector, 是 UseParallelGC 的 gc 的升级版本 , 有更好的性能或者优点 , 可以和 CMS gc 一起使用

 

e:-XX:+CMSParallelRemarkEnabled

在使用 UseParNewGC 的情况下 , 尽量减少 mark 的时间

 

f:-XX:+UseConcMarkSweepGC

指 定在 Old Generation 使用 concurrentcmark sweep gc,gc thread 和 app thread 并行 ( 在 init-mark 和 remark 时 pause app thread). app pause 时间较短 , 适合交互性强的系统 , 如 web server

 

g:-XX:+UseCMSCompactAtFullCollection

在使用 concurrent gc 的情况下 , 防止 memoryfragmention, 对 live object 进行整理 , 使 memory 碎片减少

 

h:-XX:CMSInitiatingOccupancyFraction=<n>

指示在 old generation 在使用了 n% 的比例后 , 启动 concurrentcollector, 默认值是 68, 如 :-XX:CMSInitiatingOccupancyFraction=70

 

i:-XX:+UseCMSInitiatingOccupancyOnly

指示只有在 old generation 在使用了初始化的比例后concurrent collector 启动收集

 

3:others

 

a:-XX:MaxTenuringThreshold=<n>

指 定一个 object 在经历了 n 次 young gc 后转移到 oldgeneration 区 , 在 linux64 的 java6 下默认值是 15, 此参数对于 throughput collector 无效 , 如 :-XX:MaxTenuringThreshold=31

 

b:-XX:+DisableExplicitGC

禁止 java 程序中的 full gc,如 System.gc() 的调用. 最好加上么,防止程序在代码里误用了。对性能造成冲击。

 

c:-XX:+UseFastAccessorMethods

get,set 方法转成本地代码

 

d:-XX:+PrintGCDetails

打应垃圾收集的情况如 :

[GC15610.466: [ParNew: 229689K->20221K(235968K), 0.0194460 secs]1159829K->953935K(2070976K), 0.0196420 secs]

 

e:-XX:+PrintGCTimeStamps

打应垃圾收集的时间情况 , 如 :

[Times:user=0.09 sys=0.00, real=0.02 secs]

 

f:-XX:+PrintGCApplicationStoppedTime

打应垃圾收集时 , 系统的停顿时间 , 如 :

Totaltime for which application threads were stopped: 0.0225920 seconds

 

JVM参数设置大全

http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

 

JVM参数设置大全压缩版

http://blogs.sun.com/watt/resource/jvm-options-list.html


7.     其他知识点


7.1 关于动态向常量池中添加常量和String的intern()方法


         常量池中的常量并非一定要预置在代码中,运行期间也可能将新的常量放入常量池中,String的intern()方法就是利用这个特性。


         在JDK1.6中,intern()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中的字符串实例的引用,所以这个引入跟普通的stringBuffer生成的对象引用肯定是不一样的,即时文本内容一样。


 


7.2 何时会出现加载的类太多?


         通常情况下,大量的JSP或者动态生成jsp的应用、基于OSGi的应用、动态代理(可以基于cglib,如spring AOP)等,均会动态生成class字节码,导致大量的字节码被加载,可能造成永久去溢出