Java 内存模型,内存监控,GC查看

编写不易,转载请注明( http://shihlei.iteye.com/blog/2244799)!

(一)Java 内存模型

摘自网上的内存模型图:


 

 

1)堆(heap——线程共享):实例域,静态域,数组元素。
 
(1)新生代(young generation): 新创建对象的存放区域
 
          a)伊甸区(eden):
 
          b)幸存者0(survivor0):
 
          c)幸存者1(survivor1):
 
(2)老年代(tenured | old generation):
 
2)虚拟机栈(stack——线程不共享):局部变量,方法自定义参数,异常参数。线程私有
 
3)方法区(permanent generation):保存类常量,字符串常量,加载类的素有class
 
     ——Java 8 后 Metaspace 代替 默认受物理内存限制,可以通过 -XX:MaxMetaspaceSize 设置最大使用内存数。
 
4)程序计数器
 
5)本地方法栈
 

(二)JVM 内存设置

(1)设置参数
 
-Xms250m:java 堆初始值
 
-Xmx250m:java 堆最大值
 
-XX:MaxMetaspaceSize=50m 最大Metaspace大小
 
(2)查看
 
jmap -heap 18095
 
Attaching to process ID 18095, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.31-b07
 
using thread-local object allocation.
Mark Sweep Compact GC
 
Heap Configuration:
   MinHeapFreeRatio         = 40      最小堆使用比例
   MaxHeapFreeRatio         = 70    最大堆可用比例
   MaxHeapSize              = 104857600 (100.0MB)    最大堆空间大小
   NewSize                  = 34930688 (33.3125MB)   新生代分配大小
   MaxNewSize               = 34930688 (33.3125MB)  最大可新生代分配大小
   OldSize                  = 69926912 (66.6875MB)  老生代大小
   NewRatio                 = 2 (old/young generations)  新生代比例
   SurvivorRatio            = 8 (young/suvivor ) 新生代与suvivor的比例
   MetaspaceSize            = 21807104 (20.796875MB)    Metaspace大小——   Metaspace是1.8后出现的,替代perm区
   CompressedClassSpaceSize = 1073741824 (1024.0MB)   CompressedClassSpace大小
   MaxMetaspaceSize         = 52428800 (50.0MB) : 最大 Metaspace大小
   G1HeapRegionSize         = 0 (0.0MB)
 
 
(三)垃圾回收
 
1)MinorGC:清理年轻代(eden和survior)
 
     eden满触发 eden—》s0如果此时s0满,触发s0-到s1
 
2)MajorGC:清理永久代
 
3)FullGC:清理整个堆空间,包括年轻和永久代,
 
     如果"幸存者区"满,触发"幸存者"到"老年代GC"的FullGC,幸存者区满一定会出现MinorGC,所以 FullGC 一定会出现MinorGC, MajorGC永远不会出现。
 

 (四)GC 参数:

-XX:+PrintGC 输出GC日志
 
-XX:+PrintGCDetails 输出GC的详细日志
 
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
 
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
 
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
 
-Xloggc:../logs/gc.log 日志文件的输出路径
 
 
注:PrintGC开始的参数都是可管理的GC参数,可以通过jinfo开启
 
 
如:
 
$ jinfo -flag +HeapDumpBeforeFullGC 18650  
$ jinfo -flag +HeapDumpAfterFullGC 18650
 
$ jinfo -flag -HeapDumpBeforeFullGC 18650  
$ jinfo -flag -HeapDumpAfterFullGC 18650   
 
 

 (五)GC监控及查看

1)查看对空间使用
jstat -gc vmid
 
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
3392.0 3392.0  0.0   2185.4 27328.0  21297.2   68288.0     3429.1   9216.0 8854.1 1024.0 939.1       3    0.039   2      0.037    0.076
3392.0 3392.0  0.0   2185.4 27328.0  21678.1   68288.0     3429.1   9216.0 8854.1 1024.0 939.1       3    0.039   2      0.037    0.076
3392.0 3392.0  0.0   2185.4 27328.0  22709.9   68288.0     3429.1   9216.0 8854.1 1024.0 939.1       3    0.039   2      0.037    0.076
3392.0 3392.0  0.0   2185.4 27328.0  23611.4   68288.0     3429.1   9216.0 8854.1 1024.0 939.1       3    0.039   2      0.037    0.076
3392.0 3392.0  0.0   2185.4 27328.0  24553.2   68288.0     3429.1   9216.0 8854.1 1024.0 939.1       3    0.039   2      0.037    0.076
 
S0C   :S0 总大小
S1C   :S1 总大小
S0U   :S0 使用大小
S1U   :S1 使用大小
EC     :伊甸区总大小 
EU     :伊甸区使用大小   
OC    :老年代总大小     
OU    :老年代使用大小   
MC    :Metaspace 总大小 
MU    :Metaspace 使用大小
CCSC   :CompressedClassSpace总大小
CCSU   :CompressedClassSpace使用大小
YGC     :Young GC 次数
YGCT   :Young GC 消耗总时间
FGC     :FullGC 次数
FGCT   :FullGC 消耗总时间
GCT     :GC总消耗时间  
2)查看内存占用
 
查看占用内存最大的对象
jmap -histo 18095 | head -30 
 
 num     #instances         #bytes  class name
----------------------------------------------
   1:         52644        6436448  [B
   2:         24249        3111416  [C
   3:          9522        1066464  java.net.SocksSocketImpl
   4:         15365        1029896  [Ljava.lang.Object;
   5:         48790         780640  java.lang.Object
   6:          3352         773088  [I
   7:          9521         457008  java.net.SocketInputStream
   8:          9521         457008  java.net.SocketOutputStream
   9:          9564         382560  java.lang.ref.Finalizer
  10:         15050         361200  java.lang.String
  11:          9531         304992  java.io.FileDescriptor
  12:          9521         304672  java.net.Socket
  13:         11276         270624  java.net.InetAddress$InetAddressHolder
  14:          3566         256752  org.apache.thrift.protocol.TBinaryProtocol
  15:          9652         231648  java.util.ArrayList
  16:          9523         228552  java.net.Inet4Address
  17:          2417         193360  [S
  18:          1448         153248  java.lang.Class
  19:          3523         112736  java.util.concurrent.SynchronousQueue$TransferStack$SNode
  20:          3522          84528  org.apache.thrift.protocol.TField
  21:          3521          84504  org.apache.thrift.protocol.TMessage
  22:          1786          71440  java.io.BufferedInputStream
  23:          1785          71400  org.apache.thrift.transport.TSocket
  24:          1758          70320  org.apache.thrift.transport.TTransportException
  25:          1969          63008  java.util.HashMap$Node
  26:          2613          62712  java.lang.StringBuilder
  27:          1787          42888  java.io.BufferedOutputStream
 
 
3)查看栈线程情况
查看线程cpu,内存情况
 
 ps -mp 32460 -o THREAD,tid,time
 
能看到进程cpu内存占用,线程cpu占用,看不到内存占用
 
ps -mp 32460 -o THREAD,tid,time,rss,size,%mem
USER     %CPU PRI SCNT WCHAN  USER SYSTEM   TID     TIME   RSS    SZ %MEM
root      0.0   -    - -         -      -     - 00:09:47 49416 2122256  4.8
root      0.0  19    - futex_    -      - 32460 00:00:00     -     -    -
root      0.0  19    - futex_    -      - 32461 00:00:00     -     -    -
root      0.0  19    - futex_    -      - 32462 00:00:28     -     -    -
root      0.0  19    - futex_    -      - 32463 00:00:00     -     -    -
root      0.0  19    - futex_    -      - 32464 00:00:00     -     -    -
root      0.0  19    - futex_    -      - 32465 00:00:00     -     -    -
root      0.0  19    - futex_    -      - 32466 00:00:07     -     -    -
root      0.0  19    - futex_    -      - 32467 00:00:01     -     -    -
root      0.0  19    - futex_    -      - 32468 00:00:00     -     -    - 
 
jstack -l 18095
 
 
"pool-1-thread-5" #12 prio=5 os_prio=0 tid=0x00007f60cc22f800 nid=0x724c waiting on condition [0x00007f60d106b000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000fba00b30> (a java.util.concurrent.SynchronousQueue$TransferStack)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
        at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
        at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:924)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
 
   Locked ownable synchronizers:
        - None
 
"pool-1-thread-5" 线程名称。用户自己的程序最好是线程名称
prio=5 线程优先级默认是5
tid=0x00007f60cc22f800 唯一标识
nid=0x724c  对应系统线程的id和top出来看到的pid是对应的(十进制转16进制)
RUNNABLE线程状态
 
状态如下:
1,死锁  Deadlock(重要)
2,等待资源 Waiting on condition (重要)
3,等待获取监视器waiting on monitor entry
4,阻塞Blocked
5,执行中Runnable
6,暂停Suspended
7,对象等待中Object.wait()或TIMED_WAITING
8,停止Parked
 
(六)GC 日志分析
 
[GC (Allocation Failure) [PSYoungGen(Young GC): 25872K(回收前大小)->3234K(回收后大小)(30208K)(新生代总大小)] 57740K(堆回收前大小)->39158K(堆回收后大小)(98816K)(堆总大小), 0.0006179 secs(回收时间)] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 3234K->0K(30208K)] [ParOldGen: 35924K->6596K(68608K)] 39158K->6596K(98816K), [Metaspace: 2748K->2748K(1056768K)], 0.0016981 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
 
引用
[GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs]
 
<collector>GC收集器的名称 
 
<starting occupancy1> 新生代在GC前占用的内存 
<ending occupancy1> 新生代在GC后占用的内存 
<pause time1> 新生代局部收集时jvm暂停处理的时间 
 
<starting occupancy3> JVM Heap 在GC前占用的内存 
<ending occupancy3> JVM Heap 在GC后占用的内存 
<pause time3> GC过程中jvm暂停处理的总时间  

(七)Java 程序启动脚本

#!/bin/bash

MAINCLASS=""
# add class path ---------------------------------
CLASSPATH=".."

for jar in `ls ./lib`
do
CLASSPATH="$CLASSPATH:./lib/$jar"
done

CLASSPATH="./classes:$CLASSPATH"

export CLASSPATH

# add java opts ----------------------------------

JAVA_OPTS="-Xms250m -Xmx250m -XX:MaxMetaspaceSize=50m"

#DEBUG="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8899"

GC_LOG="-XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -Xloggc:./logs/gc.log"

JAVA_OPTS="$JAVA_OPTS $DEBUG $GC_LOG"

# echo info ----------------------------------
echo "CLASSPATH : $CLASSPATH"
echo "JAVA_OPTS: $JAVA_OPTS"

nohup java $JAVA_OPTS -Dapp.base=$PWD $MAINCLASS >> /dev/null 2>&1 &

猜你喜欢

转载自shihlei.iteye.com/blog/2244799