Java高性能分析

最近查问题时候发现广告引擎的调度中心的定时执行任务执行时间过长,最近这接近一年多只忙于业务需求的开发,是优化各模块的时候了,否则最后会很被动。这里使用的java优化工具,以及优化方法介绍一下,如果不是在生产环境使用,个人推荐使用Jprofiler,这个功能强大,并且美观完美:

JPS

用来查看基于HotSpot的JVM里面中,所有具有访问权限的Java进程的具体状态, 包括进程ID,进程启动的路径及启动参数等等,与unix上的ps类似,只不过jps是用来显示java进程,可以把jps理解为ps的一个子集

-q 忽略输出的类名、Jar名以及传递给main方法的参数,只输出pid。

-m 输出传递给main方法的参数,如果是内嵌的JVM则输出为null。

-l 输出应用程序主类的完整包名,或者是应用程序JAR文件的完整路径。

-v 输出传给JVM的参数。

-V 输出通过标记的文件传递给JVM的参数(.hotspotrc文件,或者是通过参数-XX:Flags=<filename>指定的文件)。

-J 用于传递jvm选项到由javac调用的java加载器中,例如,“-J-Xms48m”将把启动内存设置为48M,使用-J选项可以非常方便的向基于Java的开发的底层虚拟机应用程序传递参数。

jstack  pid

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。

查询java线程的执行情况。

基本参数:

-F当’jstack [-l] pid’没有相应的时候强制打印栈信息

-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.

-m打印java和native c/c++框架的所有栈信息.

-h | -help打印帮助信息

12:19 [[email protected]]$ jstack 6337

2016-11-13 12:19:16

Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.6-b04 mixed mode):

"resin-port-80" daemon prio=10 tid=0x000000001da87800 nid=0x1936 in Object.wait() [0x00000000462f0000]

java.lang.Thread.State: TIMED_WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x000000076fc6e998> (a com.caucho.server.port.Port)

at com.caucho.server.port.Port.run(Port.java:1287)

- locked <0x000000076fc6e998> (a com.caucho.server.port.Port)

at java.lang.Thread.run(Thread.java:722)

"resin-port-6800" daemon prio=10 tid=0x000000001da89800 nid=0x1935 in Object.wait() [0x00000000461ef000]

java.lang.Thread.State: TIMED_WAITING (on object monitor)

at java.lang.Object.wait(Native Method)

- waiting on <0x000000076fc6a1e0> (a com.caucho.server.cluster.ClusterPort)

at com.caucho.server.port.Port.run(Port.java:1287)

- locked <0x000000076fc6a1e0> (a com.caucho.server.cluster.ClusterPort)

at java.lang.Thread.run(Thread.java:722)

"PromotedConfigTask-23-thread-1" daemon prio=10 tid=0x000000001d6b2000 nid=0x1934 waiting on condition [0x00000000460ee000]

java.lang.Thread.State: TIMED_WAITING (parking)

at sun.misc.Unsafe.park(Native Method)

- parking to wait for  <0x0000000774792478> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)

at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)

at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)

at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1090)

at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:807)

at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)

at java.lang.Thread.run(Thread.java:722)

线程状态的分析

死锁,Deadlock(重点关注)

执行中,Runnable

等待资源,Waiting on condition(重点关注)

如果发现有大量的线程都在处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几 乎消耗了所有的带宽,仍然有大量数据等待网络读 写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如
netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的 CPU时间,相对于用户态的 CPU时间比例较高;

等待获取监视器,Waiting on monitor entry(重点关注)

暂停,Suspended

对象等待中,Object.wait() 或 TIMED_WAITING

阻塞,Blocked(重点关注)

停止,Parked

TIMED_WAITING (parking):这里指定了时间,到达指定的时间后自动退出等待状态;parking指线程处于挂起中

jstat

Jstat用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计,使用jstat我们可以对指定的JVM做如下监控:

- 类的加载及卸载情况

- 查看新生代、老生代及持久代的容量及使用情况

- 查看新生代、老生代及持久代的垃圾收集情况,包括垃圾回收的次数及垃圾回收所占用的时间

- 查看新生代中Eden区及Survior区中容量及分配情况等

jstat的使用需要对JVM内存模型有充分的了解,如果不熟悉,先查阅JVM内存模型相关知识。

根据jstat统计的维度不同,可以使用如下表中的选项进行不同维度的统计,不同的操作系统支持的选项可能会不一样,可以通过-options选项,查看不同操作系统所支持选项,如:

Option Displays...
class 用于查看类加载情况的统计
compiler 用于查看HotSpot中即时编译器编译情况的统计
gc 用于查看JVM中堆的垃圾收集情况的统计
gccapacity 用于查看新生代、老生代及持久代的存储容量情况
gccause 用于查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因。
gcnew 用于查看新生代垃圾收集的情况
gcnewcapacity 用于查看新生代的存储容量情况
gcold 用于查看老生代及持久代发生GC的情况
gcoldcapacity 用于查看老生代的容量
gcpermcapacity 用于查看持久代的容量
gcutil 用于查看新生代、老生代及持代垃圾收集的情况
printcompilation HotSpot编译方法的统计

    vmid  - VM的进程号,即当前运行的java进程号。

还有两个关于显示频率的选项:

    interval–间隔时间,单位可以是秒或者毫秒,通过指定s或ms确定,默认单位为毫秒。

    count-打印次数,如果缺省则打印无数次。

3、不同的统计维度(statOption)及输出说明

-class

类加载情况的统计
列名 说明
Loaded 加载了的类的数量
Bytes 加载了的类的大小,单为Kb
Unloaded 卸载了的类的数量
Bytes 卸载了的类的大小,单为Kb
Time 花在类的加载及卸载的时间

-compiler

HotSpot中即时编译器编译情况的统计
列名 说明
Compiled 编译任务执行的次数
Failed 编译任务执行失败的次数
Invalid 编译任务非法执行的次数
Time 执行编译花费的时间
FailedType 最后一次编译失败的编译类型
FailedMethod 最后一次编译失败的类名及方法名

-gc

JVM中堆的垃圾收集情况的统计
列名 说明
S0C 新生代中Survivor space中S0当前容量的大小(KB)
S1C 新生代中Survivor space中S1当前容量的大小(KB)
S0U 新生代中Survivor space中S0容量使用的大小(KB)
S1U 新生代中Survivor space中S1容量使用的大小(KB)
EC Eden space当前容量的大小(KB)
EU Eden space容量使用的大小(KB)
OC Old space当前容量的大小(KB)
OU Old space使用容量的大小(KB)
PC Permanent space当前容量的大小(KB)
PU Permanent space使用容量的大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
YGCT 从应用程序启动到采样时 Young GC 所用的时间(秒)
FGC 从应用程序启动到采样时发生 Full GC 的次数
FGCT 从应用程序启动到采样时 Full GC 所用的时间(秒)
GCT T从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC

-gccapacity

新生代、老生代及持久代的存储容量情况
列名 说明
NGCMN 新生代的最小容量大小(KB)
NGCMX 新生代的最大容量大小(KB)
NGC 当前新生代的容量大小(KB)
S0C 当前新生代中survivor space 0的容量大小(KB)
S1C 当前新生代中survivor space
1的容量大小(KB)
EC Eden space当前容量的大小(KB)
OGCMN 老生代的最小容量大小(KB)
OGCMX 老生代的最大容量大小(KB)
OGC 当前老生代的容量大小(KB)
OC 当前老生代的空间容量大小(KB)
PGCMN 持久代的最小容量大小(KB)
PGCMX 持久代的最大容量大小(KB)
PGC 当前持久代的容量大小(KB)
PC 当前持久代的空间容量大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
FGC 从应用程序启动到采样时发生 Full GC 的次数

-gccause

这个选项用于查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因,它比-gcutil会多出最后一次垃圾收集原因以及当前正在发生的垃圾收集的原因。

用于查看垃圾收集的统计情况,包括最近发生垃圾的原因
列名 说明
LGCC 最后一次垃圾收集的原因,可能为“unknown GCCause”、“System.gc()”等
GCC 当前垃圾收集的原因

-gcnew

新生代垃圾收集的情况
列名 说明
S0C 当前新生代中survivor space 0的容量大小(KB)
S1C 当前新生代中survivor space 1的容量大小(KB)
S0U S0已经使用的大小(KB)
S1U S1已经使用的大小(KB)
TT Tenuring threshold,要了解这个参数,我们需要了解一点Java内存对象的结构,在Sun JVM中,(除了数组之外的)对象都有两个机器字(words)的头部。第一个字中包含这个对象的标示哈希码以及其他一些类似锁状态和等标识信息,第二个字中包含一个指向对象的类的引用,其中第二个字节就会被垃圾收集算法使用到。

在新生代中做垃圾收集的时候,每次复制一个对象后,将增加这个对象的收集计数,当一个对象在新生代中被复制了一定次数后,该算法即判定该对象是长周期的对象,把他移动到老生代,这个阈值叫着tenuring threshold。这个阈值用于表示某个/些在执行批定次数youngGC后还活着的对象,即使此时新生的的Survior没有满,也同样被认为是长周期对象,将会被移到老生代中。

MTT Maximum tenuring threshold,用于表示TT的最大值。
DSS Desired survivor size (KB).可以参与这里:http://blog.csdn.net/yangjun2/article/details/6542357
EC Eden space当前容量的大小(KB)
EU Eden space已经使用的大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
YGCT 从应用程序启动到采样时 Young GC 所用的时间(单位秒)

-gcnewcapacity

新生代的存储容量情况
列名 说明
NGCMN           新生代的最小容量大小(KB)
NGCMX     新生代的最大容量大小(KB)
NGC     当前新生代的容量大小(KB)
S0CMX 新生代中SO的最大容量大小(KB)
S0C 当前新生代中SO的容量大小(KB)
S1CMX 新生代中S1的最大容量大小(KB)
S1C 当前新生代中S1的容量大小(KB)
ECMX 新生代中Eden的最大容量大小(KB)
EC 当前新生代中Eden的容量大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
FGC 从应用程序启动到采样时发生 Full GC 的次数

-gcold

老生代及持久代发生GC的情况
列名 说明
PC 当前持久代容量的大小(KB)
PU 持久代使用容量的大小(KB)
OC 当前老年代容量的大小(KB)
OU 老年代使用容量的大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
FGC 从应用程序启动到采样时发生 Full GC 的次数
FGCT 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC

-gcoldcapacity

老生代的存储容量情况
列名 说明
OGCMN 老生代的最小容量大小(KB)
OGCMX 老生代的最大容量大小(KB)
OGC 当前老生代的容量大小(KB)
OC 当前新生代的空间容量大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
FGC 从应用程序启动到采样时发生 Full GC 的次数
FGCT 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC

-gcpermcapacity

从应用程序启动到采样时发生 Full GC 的次数

持久代的存储容量情况
列名 说明
PGCMN 持久代的最小容量大小(KB)
PGCMX 持久代的最大容量大小(KB)
PGC 当前持久代的容量大小(KB)
PC 当前持久代的空间容量大小(KB)
YGC 从应用程序启动到采样时发生 Young GC 的次数
FGC
FGCT 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC

-gcutil

新生代、老生代及持代垃圾收集的情况
列名 说明
S0 Heap上的 Survivor space 0 区已使用空间的百分比
S1 Heap上的 Survivor space 1 区已使用空间的百分比
E Heap上的 Eden space 区已使用空间的百分比
O Heap上的 Old space 区已使用空间的百分比
P Perm space 区已使用空间的百分比
YGC 从应用程序启动到采样时发生 Young GC 的次数
YGCT 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC 从应用程序启动到采样时发生 Full GC 的次数
FGCT 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT 从应用程序启动到采样时用于垃圾回收的总时间(单位秒),它的值等于YGC+FGC

-printcompilation

HotSpot编译方法的统计
列名 说明
Compiled 编译任务执行的次数
Size 方法的字节码所占的字节数
Type 编译类型
Method 指定确定被编译方法的类名及方法名,类名中使名“/”而不是“.”做为命名分隔符,方法名是被指定的类中的方法,这两个字段的格式是由HotSpot中的“-XX:+PrintComplation”选项确定的。

例如:

13:03 [[email protected]]$ jstat -gcutil 6337 1000 5

S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT

0.00 100.00  25.81  47.68  13.63   4523  994.726   668  534.859 1529.584

0.00 100.00  28.39  47.68  13.63   4523  994.726   668  534.859 1529.584

0.00 100.00  31.25  47.68  13.63   4523  994.726   668  534.859 1529.584

0.00 100.00  33.48  47.68  13.63   4523  994.726   668  534.859 1529.584

0.00 100.00  34.79  47.68  13.63   4523  994.726   668  534.859 1529.584

每1秒打印一次,共打印5次

jmap

打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)帮着我们分析对象的内存占用情况,来优化内存。

基本参数:

-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.

-finalizerinfo 打印正等候回收的对象的信息.

-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.

-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.

-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.

-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.

-h | -help 打印辅助信息

-J 传递参数给jmap启动的jvm.

pid 需要被打印配相信息的java进程id,创业与打工的区别 - 博文预览,可以用jps查问.

例如:

13:13 [[email protected]]$ jmap -histo 6337 | head -n100

num     #instances         #bytes  class name

----------------------------------------------

1:       2887052      314764096  [C

2:       3803222      121703104  java.util.HashMap$Entry

3:        128369       79413312  [B

4:       2792247       67013928  java.lang.String

5:         34567       42500808  [I

6:       2458631       39338096  java.lang.Integer

7:        416678       37559864  [Ljava.util.HashMap$Entry;

8:        461445       24780696  [Ljava.lang.Object;

9:        410931       23012136  java.util.HashMap

10:        535284       17129088  com.youku.atm.common.module.MIdeaTime

同时也可以将信息打印到二进制文件中使用mat工具分析:

13:14 [[email protected]]$ jmap -dump:format=b,file=test.bin 6337

Dumping heap to /opt/flamegraph/test.bin ...

Heap dump file created

jinfo

查看jvm内存各种配置信息

13:18 [[email protected]]$ jinfo 6337

Attaching to process ID 6337, please wait...

Debugger attached successfully.

Server compiler detected.

JVM version is 23.6-b04

Java System Properties:

java.runtime.name = Java(TM) SE Runtime Environment

java.vm.version = 23.6-b04

sun.boot.library.path = /usr/java/jdk1.7.0_11/jre/lib/amd64

javax.management.builder.initial = com.caucho.jmx.MBeanServerBuilderImpl

java.vendor.url = http://java.oracle.com/

java.vm.vendor = Oracle Corporation

jConsole

jconsole、jviusalvm都是图形化看java内存、线程、cpu等的工具,可以本地也可以远程,连接远程都需要配置resin 的jvm参数,开启rmi服务

具体在resin中的配置如下:

同时也可以将信息打印到二进制文件中使用mat工具分析:

<jvm-arg>-Dcom.sun.management.jmxremote.port=8888</jvm-arg>

<jvm-arg>-Dcom.sun.management.jmxremote.ssl=false</jvm-arg>

<jvm-arg>-Dcom.sun.management.jmxremote.password=false</jvm-arg>

<jvm-arg>-Dcom.sun.management.jmxremote.authenticate=false</jvm-arg>

<jvm-arg>-Djava.rmi.server.hostname=10.100.51.53</jvm-arg>

jviusalvm

也需要配置远程,具体配置和jconsole相同,但是要不jconsole功能更强大,更美观

jProfiler

jprofiler是商业性的java性能优化工具,功能更强大,可以看对象占用内存、热点对象、热点方法、对象引用情况、CPU使用情况、线程运行情况、方法的调用tree、每个方法的耗时分析等功能。但是JProfiler是消耗系统资源的,切记不能在生产环境使用。

具体使用方法如下:

安装下载路径:http://www.ej-technologies.com/download/jprofiler/files

Window安装客户端

Jprofiler9.2在window中安装注册码:http://blog.csdn.net/t0591/article/details/52493394

并且linux服务器中安装配置:

在resin中配置需要以下两部分:

resin3的配置,在resin.conf中的

<class-loader>..</class-loader>中间添加

<tree-loader path="/opt/flamegraph/jprofiler9/lib" />

<tree-loader path="/opt/flamegraph/jprofiler9/lib" />

在<server-default>...</server-default>中加入

<jvm-arg>-agentpath:/opt/flamegraph/jprofiler9/bin/linux-x64/libjprofilerti.so=port=8849,nowait</jvm-arg>

然后可以在window的图形界面上链接linux的服务端口8849

然后既可以开启jprofiler的性能分析之旅

方法调用tree,看方法执行时间、性能:

cpu负载、线程、class加载、gc的情况

参考博主:

http://blog.csdn.net/fenglibing/article/details/6411940

http://jameswxx.iteye.com/blog/1041173

时间: 2024-10-21 10:22:57

Java高性能分析的相关文章

java代码分析及分析工具

java代码分析及分析工具 一个项目从搭建开始,开发的初期往往思路比较清晰,代码也比较清晰.随着时间的推移,业务越来越复杂.代码也就面临着耦合,冗余,甚至杂乱,到最后谁都不敢碰. 作为一个互联网电子商务网站的业务支撑系统,业务复杂不言而喻.从09年开始一直沿用到现在,中间代码经过了多少人的手,留下了多少的坑,已经记不清楚了,谁也说不清了. 代码的维护成本越来越高.代码已经急需做调整和改善.最近项目组专门设立了一个小组,利用业余时间做代码分析的工作,目标对核心代码进行分析并进行设计重构. 代码分析

HDFS API的java代码分析与实例

HDFS API的java代码分析与实例 1.HDFS常用的方法,我已经写好,我们看一下 // Create()方法,直接在HDFS中写入一个新的文件,path为写入路径,text为写入的文本内容 public static void  Create(String path,String text) throws IOException {             Configuration conf=new Configuration();                  conf.set(

J2SE快速进阶——Java内存分析

程序的执行过程 要在Java中分析内存,我们先来了解一下程序的执行过程: 正如上图所示,大致分为3个步骤: 1.最开始,我们的程序是存在于硬盘中的,当启动运行时,程序会被加载(load)到内存中去,这里的内存可以看做我们的内存条: 2.此时,内存中除了存在刚加载的程序的代码,还存在操作系统本身的代码(好吧,此句可以当做废话→_→),操作系统会找到程序中的Main方法开始执行程序: 3.第三步就是本文的重点,系统在程序执行过程中对内存的管理.在Java中,内存大致会被分为四块--heap(栈).s

学java教程之java内存分析

学编程吧学java教程之java内存分析发布了,欢迎大家通过xuebiancheng8.com来访问 java的内存模型是java中非常重要的知识,也是面试的时候重点. java虚拟机的内存模型中和我们打交道多的分为这么几个区域 堆区,栈区,方法区. 其中方法区又分为常量池,静态区和方法区. 这几部分分别是干嘛的呢,堆区是用来存放new出来的对象的,堆区是应用程序共享的区域. 栈区又叫方法栈,程序在运行的时候,代码要在方法栈中运行,运行的代码需要放在方法栈中来执行,然后寄存器一行一行加载执行.

Java AsyncTask 分析内部实现

sdk3.0前,使用内部的线程池,多线程并发执行.线程池大小等于5,最大达128 sdk3.0后,使用默认的serial线程池,执行完一个线程,再顺序执行下一个线程.sdk4.3时 线程池大小等于5,最大达128 sdk4.4后线程池大小等于 cpu count + 1,最大值为cpu count * 2 + 1 sdk3.0后有两种线程池的实现,默认为 Serial 线程池 public static final Executor SERIAL_EXECUTOR = new SerialExe

Java性能优化指南系列(二):Java 性能分析工具

进行JAVA程序性能分析的时候,我们一般都会使用各种不同的工具.它们大部分都是可视化的,使得我们可以直观地看到应用程序的内部和运行环境到底执行了什么操作,所以性能分析(性能调优)是依赖于工具的.在第2章,我强调了基于数据驱动的性能测试是非常重要的,我们必须测试应用的性能并理解每个指标的含义.性能分析和数据驱动非常类似,为了提升应用程序的性能,我们必须获取应用运行的相关数据.如何获取这些数据并理解它们是本章的主题.[本章重点介绍JDK中提供的性能分析工具] 操作系统工具及其分析 程序分析的起点并不

java内存分析总结

1.自带的jconsole工具. (1)如果是从命令行启动,使 JDK 在 PATH 上,运行 jconsole 即可. (2)如果从 GUI shell 启动,找到 JDK 安装路径,打开 bin 文件夹,双击 jconsole . (3)当分析工具弹出时(取决于正在运行的 Java 版本以及正在运行的 Java 程序数量),可能会出现一个对话框,要求输入一个进程的 URL 来连接, 也可能列出许多不同     的本地 Java 进程(有时包含 JConsole 进程本身)来连接. 参照htt

Java 性能分析工具 , 第 2 部分:Java 内置监控工具

引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工具,其中包括: jcmd:打印一个 Java 进程的类,线程以及虚拟机信息.适合用在脚本中.使用 jcmd - h 来查看使用方法. jconsole:提供 JVM 活动的图形化展示,包括线程使用,类使用以及垃圾回收(GC)信息. jhat:帮助分析内存堆存储. jmap:提供 JVM 内存使用信息

关于java内存分析的探讨

这些天一直都想找个机会把Java内存方面的知识整理整理,毕竟任何知识都涉及到这方面.Java内存分析是java学习的一大重点. 下面我们进入正式话题讨论: 我们知道Java内存大致分为三块:如下图 我们先大致了解下java各分区的数据存放内容: 栈区:主要为方法服务,存在许许多多的方法栈帧,在方法栈帧里开辟局部变量开辟空间,基本类型按基本数据类型数据大小开辟空间,而引用类型则开辟四个字节大小. 堆区:主要存放创建的对象数据. 方法区:主要存放加载的类,静态变量,静态初始化块,常量,以及程序运行的