一块很小的内存空间html
一般存放基本数据类型,对象引用(一个指向对象起始地址的引用指针或一个表明对象的句柄),reeturnAddress类型(指向一条字节码指令的地址)java
与虚拟机栈类似,主要为虚拟机使用到的Native方法服务,在HotSpot虚拟机中直接把本地方法栈与虚拟机栈二合一linux
和虚拟机栈同样可能抛出StackOverflowError和OutOfMemoryError异常。算法
java堆是被全部线程共享的一块内存区域,在虚拟机启动时建立。此区域的惟一目的就是存储对象实例。java堆是垃圾收集器管理的主要区域。java堆还能够细分为:新生代与老年代。再细一点有Eden空间、Form Survivor空间、To Survivor空间等。数据库
直接内存并非虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,是jvm外部的内存区域,这部分区域也可能致使OutOfMemoryError异常。ubuntu
其实这些算法和OOM没有太大关系,OOM产生的缘由很简单,就是须要内存的时候没有内存了,可是对垃圾回收机制的理解可让咱们知道-Xmx -Xms Xmn – MaxPermSize参数该怎么样设置,避免频繁full-GC(Full-GC会形成app短暂停顿,此时app是不会响应任何客户端请求的),而且合理设置参数.(1对于缓存过多的系统能够增大-Xmx,经过减少Xmn调整新生代年老代比例,2对于瞬时对象过多的系统,年老代的heap能够不用分配那么大)缓存
HotSpot JVM一共有4个垃圾回收器:Serial(串行)、Parallel / Throughput(并行)、CMS(并发)、and the new kid on the block G1(G1)。HotSpot默认使用Parallel / Throughput回收器,但它经常不是你运行程序的最佳选择。好比CMS和G1会使GC停顿(GC pause)发生的频率下降,可是对于每次停顿所花费的时间,极可能比Parallel回收器更长。在使用相同大小堆内存的状况下,Parallel回收器能带来更高的吞吐量。因此,须要根据可接受的GC停顿频率和持续时间,选择合适的垃圾回收器。
GC算法自己能够是串行的(单线程),也能够是并行的(多线程)。所以当咱们提到并发的GC时,并不表明它是并行完成的,相反当提到串行GC时,也并不意味着就必定会出现GC停顿。在GC的世界中,并发和并行是两个彻底不一样的概念。并发针对的是GC周期,而并行针对GC算法自身。tomcat
Java 7中引入了G1回收器,它是JVM垃圾回收器中最新的组件。G1最大的优点就是解决了CMS中常见的内存碎片问题:GC周期会从老年代(Old Generation)中释放内存块,结果内存变得像瑞士奶酪那样千疮百孔,直到JVM对其无从下手了,才不得不停下来处理这些碎片。可是某些状况下其余回收器可能比G1有更好的表现,这彻底取决于你的需求(能够经过GC日志分析)服务器
如上图所示,为Java堆中的各代分布。多线程
除了程序计数器外,虚拟机内存的其余几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能,
Java Heap 溢出
通常的异常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用于存储对象实例,咱们只要不断的建立对象,而且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。
出现这种异常,通常手段是先经过内存映像分析工具(如Eclipse Memory Analyzer)对dump出来的堆转存快照进行分析,重点是确认内存中的对象是不是必要的,先分清是由于内存泄漏(Memory Leak)仍是内存溢出(Memory Overflow)。
若是是内存泄漏,可进一步经过工具查看泄漏对象到GC Roots的引用链。因而就能找到泄漏对象时经过怎样的路径与GC Roots相关联并致使垃圾收集器没法自动回收。
若是不存在泄漏,那就应该检查虚拟机的参数(-Xmx与-Xms)的设置是否适当。
若是线程请求的栈深度大于虚拟机所容许的最大深度,将抛出StackOverflowError异常。
若是虚拟机在扩展栈时没法申请到足够的内存空间,则抛出OutOfMemoryError异常
这里须要注意当栈的大小越大可分配的线程数就越少。
异常信息:java.lang.OutOfMemoryError:PermGen space
若是要向运行时常量池中添加内容,最简单的作法就是使用String.intern()这个Native方法。该方法的做用是:若是池中已经包含一个等于此String的字符串,则返回表明池中这个字符串的String对象;不然,将此String对象包含的字符串添加到常量池中,而且返回此String对象的引用。因为常量池分配在方法区内,咱们能够经过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量池的容量。
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。
异常信息:java.lang.OutOfMemoryError:PermGen space
方法区溢出也是一种常见的内存溢出异常,一个类若是要被垃圾收集器回收,断定条件是很苛刻的。在常常动态生成大量Class的应用中,要特别注意这点
生成Dump快照文件:
先经过内存映像分析工具(如Eclipse的Memory Analyzer)进行分析,常见的状况有:
1 先采用jps 或ps -ef|grep xxx找到 JAVA 程序的PID
2 利用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid 找到占用CPU最高的的线程列表
如 ps -mp 2633 -o THREAD,tid,time | sort -rn |head -10
3 将线程ID转化为十六进制 printf "%x\n" 21742,好比获得: aaee
4 打印线程的堆栈信息 jstack 2633 |grep e18 -A 30 若是运行在64位JVM上,可能须要指定-J-d64命令选项参数。
5 根据提示,调整代码,从新发布程序
1 jmap -permstat pid
打印进程的类加载器和类加载器加载的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息
2 jmap -heap pid
使用jmap -heap pid查看进程堆内存使用状况,包括使用的GC算法、堆配置参数和各代中堆内存使用状况
3 jmap -histo[:live] pid
使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,若是带上live则只统计活对象
4 jmap -dump:format=b,file=dumpFileName pid
用jmap把进程内存使用状况dump到文件中,再用jhat分析查看。jmap进行dump命令格式以下 jmap -dump:format=b,file=/tmp/dump.dat 21711
注意若是Dump文件太大,可能须要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
vmid是Java虚拟机ID,在Linux/Unix系统上通常就是进程ID。interval是采样时间间隔。count是采样数目。好比下面输出的是GC信息,采样时间间隔为250ms,采样数为4:
jstat -gc pid 60000 60
root@ubuntu:/# jstat -gc 21711 250 4 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 192.0 192.0 64.0 0.0 6144.0 1854.9 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649 192.0 192.0 64.0 0.0 6144.0 1972.2 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649
各列的含义:
S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used) EC、EU:Eden区容量和使用量 OC、OU:年老代容量和使用量 PC、PU:永久代容量和使用量 YGC、YGT:年轻代GC次数和GC耗时 FGC、FGCT:Full GC次数和Full GC耗时 GCT:GC总耗时
若是分析结果代表执行GC的时间只有0.1-0.3秒,那你就不必浪费时间去进行GC优化。可是,若是GC的执行时间是1-3秒,或者超过10秒,GC将势在必行。
hprof可以展示CPU使用率,统计堆内存使用状况。
不多使用,常用java core来分析
Java程序运行时,有时会产生JavaCore及HeapDump文件,它通常发生于Java程序遇到致命问题的状况下。
为了可以保留Java应用发生致命错误前的运行状态,JVM在死掉前产生两个文件,分别为JavaCore及HeapDump文件。
可使用IBM的HeapAnalyzer工具分析
HeapDump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用状况,这种文件须要相应的工具进行分析,如IBM Heap Analyzer这类工具。这类文件最重要的做用就是分析系统中是否存在内存溢出的状况。
可使用IBM的jca工具分析
一般状况下,频繁发生core dump是因为如下两类缘由致使: 内存泄漏、内存碎片的问题
JavaCore文件主要保存的是Java应用各线程在某一时刻的运行的位置,即JVM执行到哪个类、哪个方法、哪个行上。它是一个文本文件,打开后能够看到每个线程的执行栈,以stack trace的显示。经过对JavaCore文件的分析能够获得应用是否“卡”在某一点上,即在某一点运行的时间太长,例如数据库查询,长期得不到响应,最终致使系统崩溃等状况。
可使用IBM的ga(IBM Pattern Modeling and Analysis Tool for Java Garbage Collector) 工具分析
只要在WebSphere管理控制台的java进程属性里勾选“详细垃圾回收”
GC优化的最基本原则是将不一样的GC参数用于2台或者多台服务器,并进行对比,并将那些被证实提升了性能或者减小了GC执行时间的参数应用于服务器。请谨记这一点。
GC优化须要考虑的Java参数
定义 |
参数 |
描述 |
堆内存空间 |
-Xms |
Heap area size when starting JVM 启动JVM时的堆内存空间。 |
-Xmx |
Maximum heap area size 堆内存最大限制 |
|
新生代空间 |
-XX:NewRatio |
Ratio of New area and Old area 新生代和老年代的占比 |
-XX:NewSize |
New area size 新生代空间 |
|
-XX:SurvivorRatio |
Ratio ofEdenarea and Survivor area 伊甸园空间和幸存者空间的占比 |
我在进行GC优化时常用-Xms,-Xmx和-XX:NewRatio。-Xms和-Xmx是必须的。你如何设定NewRatio 会对GC性能产生十分显著的影响。有些人可能会问如何设定Perm区域的大小?你能够经过-XX:PermSize 和-XX:MaxPermSize参数来设定,
当OutOfMemoryError 错误发生而且是因为Perm空间不足致使时,另外一个可能影响GC性能的参数是GC类型。下表列出了全部可选的GC类型(基于JDK6.0)
GC类型可选参数
分类 |
参数 |
备考 |
Serial GC |
-XX:+UseSerialGC |
|
Parallel GC |
-XX:+UseParallelGC |
|
Parallel Compacting GC |
-XX:+UseParallelOldGC |
|
CMS GC |
-XX:+UseConcMarkSweepGC |
|
G1 |
-XX:+UnlockExperimentalVMOptions |
在JDK6中这两个参数必须同时使用 |
除了G1 GC,能够经过每种类型第一行的参数来切换GC类型。最经常使用的GC类型是Serial GC。他专门针对客户端系统进行了优化。
影响GC性能的参数有不少,可是上面提到的参数会带来最显著的效果。请牢记,设定过多的参数不必定会减小GC执行时间
成为Java GC专家—如何优化Java垃圾回收机制的系列文章
http://www.importnew.com/author/wangxiaojie
http://www.importnew.com/1993.html
http://www.importnew.com/2057.html
http://www.importnew.com/3146.html
http://www.importnew.com/3151.html