[转]使用Java Mission Control进行内存分配分析

jdk7u40自带了一个非常好用的工具,就是Java Mission ControlJRockit Misson Control用户应该会对mission control的很多功能十分熟悉,JRockit也是一款很棒的工具。本篇文章将着重关注如何使用Java Flight Recorder进行内存分配分析。

jvm有着非常棒的小块内存虚拟化技术,这会让你产生一种拥有无限内存的错觉感,其实它的开销非常大。有时候jvm需要找出此刻堆上数据是如何被使用的,并把剩余的空间扩大——这就是垃圾回收。产生这种情况的原因是,jvm实际获得的物理内存是有限的,因此需要在不被使用时进行内存回收和复用。在一些时间敏感的应用中,比如交易系统和通信程序,这些暂停是不能容忍的。有很多GC调优方法可以避免这种暂停发生。貌似上面的讨论已经跑题了。让GC变少的方法当然是尽量减少分配内存。

有时候,你希望找出在你的程序中哪些地方导致了内存分配的压力。引起这种压力的原因有很多种。最普通的一种情况可能是jvm需要经常GC,并且时间远超过你认为的合理值。

JFR分配事件

在HotSpot7u40中实现的Java Flight Recorder(JFR)有两种内存分配事件可以帮助我们找出程序中进行内存分配的地方:TLAB中的内存分配和TLAB外的内存分配事件。

与JDK提供的其它大多数事件相类似,有一系列可在Mission Control中进行定制的分析接口。在进行分析之前,我们要花上几分钟来讨论下实际的事件。

首先,你需要确保事件已近被记录了。如果你使用默认的模板选项,你会发现内存分配分析选项默认是关闭的。要么打开它,或者使用分析模板而不要使用默认模板。内存分析选项默认关闭的原因是,它可能会产生太多的事件。并且对于不同的程序它的性能消耗是不确定的,因为不同的程序在内存分配的情况上是差别是很大的。

事件标签组中的Log标签是查看每个单独事件的绝佳地址。我们来看看这里包括了哪些内容:

这里包括已经分配的内存确切大小、导致内存分配的堆栈轨迹、分配内存的类和事件信息。在TLAB内存分配事件中,它们还包括分配的TLAB大小。

需要注意的是,TLAB的内存分配事件中并不是对应每一个地点的内存分配事件,那样太消耗资源了。取而代之的是,我们只在新的TLAB中第一次分配内存时进行事件上报。这意味着我们只获得了本地线程的内存分配一些排序后的样本。

此外,需要注意的是我们在JRockit中使用的TLA事件和在新生代中进行的分配是完全相同的,大对象分配事件和老生代内存分配时相同的。不过这些在HotSpot中有点复杂。TLAB外的内存分配事件既可以和年轻代内存回收分配相同,也可以和后续的Eden区及old区域的直接大对象分配相同。换句话说,如果你在TLAB事件外发现了一些少量的内存分配,你并不需要担心。正常来说,这种情况是非常的少见的。因此在实际情况中这些区分并不是那么明显。

使用Allocation标签页

Allocation(分配)标签页实际上包含三个子标签页:

  1. 通用
  2. 新TLAB分配
  3. TLAB外分配

通用标签页提供了一个总的视图和一些可用事件的统计信息,例如对于不同的事件类型分配的总内存。依据你首要目标的不同,对待这些信息的方式也会不同。下面的这个例子十分精简并且聚焦在内部TLAB分配,因为它更关注于总的内存分配压力。

新TLAB分配提供了三种以上专供于分析新TLAB分配事件的虚拟化类型:类级、线程级和分析级的分配。分析级分配是对这三种类型的一个简单的栈追踪集合。从下面的这个例子可以看出,Integer对象几乎占到整个系统的所有内存分配。在直方图中选择Integer类便会显示出对Integer对象的所有内存的栈轨迹集合,同时在这个例子中,所有的分配都来自同一个地点,正如下图展示的那样。

TLAB外分配的内存标签页和新TLAB标签页的工作原理相同,仅仅在这个时间点是一致的,当然这些是TLAB外的事件。

限制

因为新TLAB的内存分配事件仅仅只是总的线程本地内存分配的样本,仅仅只有一个事件是很难说明实际情况的。更多的事件才会有更精确的图片。此外,如果分配事件的行为在记录期间变化非常大,那么这样也很难建立一个十分有说服力本地内存分配视图。

原文链接: hirt 翻译: ImportNew.com潘 凌霄
译文链接: http://www.importnew.com/13346.html
转载请保留原文出处、译者和译文链接。]

时间: 2024-08-15 11:01:15

[转]使用Java Mission Control进行内存分配分析的相关文章

java学习-----jvm的内存分配及运行机制

VM运行时数据区域: 根据<Java虚拟机规范(第二版)>的规定,JVM包括下列几个运行时区域: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的

java\c程序的内存分配

JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机.只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行.本文首先简要介绍从Java文件的编译到最终执行的过程,随后对JVM规格描述作一说明. 一.Java源文件的编译.下载.解释和执行 Java应用程序的开发周期包括编译.下载.解释和执行几个部分.Java编译程序将Java源程序翻译为JVM可执行代码?字节码.这一编译过程同C/C++的编译有

Java 中数组的内存分配

Java 中数组的内存分配 1.Java 程序在运行时,需要在内存中分配空间.为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据和内存管理方式. 2.数组基本概念 数组是存储同一种数据类型多个元素的容器. 数组既可以存储基本数据类型,也可以存储引用数据类型. 格式:数据类型[] 数组名 ; int[] arr; 数组的初始化方式: 动态初始化 : 初始化时只指定数组长度,由系统为数组分配初始值. 格式:数据类型[] 数组名 = new 数据类型[数组长度]; 数组长

java内存分配分析/栈内存、堆内存

前言 本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 进入正题前首先要知道的是Java程序运行在JVM(Java Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性.所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提

JAVA中堆栈和内存分配

(一).栈.堆 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中.)3. 堆:存放所有new出来的对象.4. 静态域(属于方法区) :存放静态成员(static定义的)5. 常量池 (属于方法区):存放字符串常量和基本类型常量(public static final).6. 非RAM存储:硬盘等永久存储空间这里我们主要关心栈

Java虚拟机7:内存分配原则

http://www.cnblogs.com/xrq730/p/4841177.html 前言 对象的内存分配,往大的方向上讲,就是在堆上分配,少数情况下也可能会直接分配在 老年代中,分配的规则并不是百分之百固定的,其细节决定于当前使用的是哪种垃圾收集器组合,当然还有虚拟机中与内存相关的参数.垃圾收集器组合一般就是 Serial+Serial Old和Parallel+Serial Old,前者是Client模式下的默认垃圾收集器组合,后者是Server模式下的默认垃圾收集器组合,文章使用对比学

Java程序运行的内存分配

Java的内存分配 A:栈 存储局部变量 B:堆 存储所有new出来的 C:方法区(面向对象部分详细讲解) D:本地方法区(系统相关) E:寄存器(CPU使用) 注意: a:局部变量 在方法定义中或者方法声明上定义的变量. b:栈内存和堆内存的区别 栈:数据使用完毕,就消失. 堆:每一个new出来的东西,且都有地址 每一个变量都有默认值 byte,short,int,long 0 float,double 0.0 char '\u0000' boolean false 引用类型 null 数据使

转!!Java虚拟机堆的内存分配和回收

Java内存分配和回收,主要就是指java堆的内存分配和回收.java堆一般分为2个大的区域,一块是新生代,一块是老年代.在新生代中又划分了3块区域,一块eden区域,两块surviver区域.一般称为from surviver和to surviver.这些区域的大小可以自己指定.比如:(-Xms20M 表示可用堆内存大小:-Xmx40M 表示最大堆内存,在堆内存大小不够时,会扩展到最大堆内存:-Xmn10M 表示新生代内存大小). 新生代中的对象会在eden区域分配,然后eden区域的内存不够

Java GC 机制与内存分配策略

收集算法是内存回收的方法论,垃圾收集器是内存回收的具体实现 自动内存管理解决的是:给对象分配内存 以及 回收分配给对象的内存 为什么我们要了解学习 GC 与内存分配呢? 在 JVM 自动内存管理机制的帮助下,不再需要为每一个new操作写配对的delete/free代码.但出现内存泄漏和溢出的问题时,如果不了解虚拟机是怎样使用内存的,那么排查错误将是一项非常艰难的工作. GC(垃圾收集器)在对堆进行回收前,会先确定哪些对象"存活",哪些已经"死去".那么就有了对象存活