《JVM故障诊断指南》之1 —— JVM概览与介绍

原文链接 原文作者:Byron Kiourtzoglou 翻译:梅小西(904516706)

Oracle HotSpot JVM 内存

Java HotSpot 虚拟机堆空间

这个部分将向你介绍Oracle Java HotSpot虚拟机里不同的Java堆内存空间概览。理解这个对于任何一个涉及到线上经常出现的内存问题的解决非常重要。而具有合适的Java 虚拟机堆空间的知识是很关键的。

Java虚拟机是你Java程序的基础,它提供了动态内存管理服务,垃圾收集,线程,IO以及本地操作等等。

Java堆空间是运行时Java程序的内存“容器”,它为你的Java程序提供了它需要的(Java堆,本地堆)合适的内存空间,并由JVM自身管理。

JVM HotSpot内存被分为3个内存空间:
• The Java Heap(堆)
• The PermGen (持久代)
• 本地堆(C-堆)

下面是他们的详细分类:

内存空间 启动参数和调整方法 监控方式 描述
Java 堆 -Xmx (最大堆容量)
-Xms (最小堆容量)

EX:
-Xmx1024m
-Xms1024m-verbose GC
– JMX API
– JConsole
– 其他监控工具Java堆是存储你的主要
的Java程序Class实例。持久代-XX:MaxPermSize (最大容量)
-XX:PermSize (最小容量)

EX:
-XX:MaxPermSize=512m
-XX:PermSize=256m- verbose GC
– JMX API
– JConsole
– 其他监控工具Java HotSpot虚拟机持久代空间
是一种JVM存储,主要用于存储
Class对象,如类名 ,类方法,
内部JVM对象和其他JIT优化
相关的数据。本地堆(C-堆)不支持直接配置。

对于32位的虚拟机,
C堆容量= 4 Gig –堆 – 持久代

对于64位的虚拟机,C堆容量=
服务器总物理内存
&虚拟内存-堆-持久代- 在Windows 和Linux上检查
整个进程大小
– Solaris 和Linux 下用pmap命令行
– AIX上用svmon命令C堆保存各种对象如MMAP文件,
其他JVM和第三方本地代码对象。
Java堆空间 – 概览 & 生命周期

你的Java程序生命周期通常看起来像这样:
• Java 程序编码(via Eclipse IDE etc.) ,例如 HelloWorld.java
• Java 程序编译 (Java 编译器或者第三方编译工具如Apache Ant, Apache Maven..),例如 HelloWord.class
• Java 程序启动和运行,例如通过HelloWorld.main() 方法运行。

现在我们来分析你的HelloWorld.class 程序,这样你能更好理解。
• 启动时,JVM会加载并把一些你的静态程序以及JDK库缓存到本地堆里面,包括本地库,映射文件比如你的程序Jar文件,线程比如你的程序的主启动线程等。
• JVM此时会保存你的HelloWorld.class的“静态”数据到持久代空间(Class元数据,描述信息等)
• 一旦你的程序启动,JVM开始管理,并在Java堆里为程序动态的分配内存(年轻代和老年代),这也是为什么了解你的程序需要多大内存空间是如此重要,你可以通过-Xms & -Xmx 的JVM参数恰当的调整你的Java堆大小。通过性能分析,堆转储分析允许你来决定程序的内存占用。
• 最终,当你的程序不再需要内存时,JVM也会动态的从堆里释放内存,这叫垃圾收集。这个过程通过JVM verbose GC或者一个监控工具比如Jconsole能很容易的监控到。

Java HotSpot 虚拟机持久代

Java HotSpot虚拟机持久代是JVM用来存储你的Java程序Class对象。Java堆主要用来保存实际的短期或者长期的持久代Class对象实例。

持久代本身是完全静态的,除非用第三方工具或者动态类加载中经常用到的Java反射API。

有一点很重要需要注意,这种内存存储方式只应用在Java Hotspot虚拟机上,其他的JVM比如IBM 和Oracle JRockit是没有这种固定以及可配置的持久代存储,它是用其他技术去管理非堆内存(本地内存)。

找到下面一张图,它描述了JVM HotSpot Java堆 vs 持久代 并分析他们各自关联的的属性和容量参数调整。




除了Oracle HotSpot JVM,还有其他各种供应商提供的虚拟机。接下来的部分我们将分析其他JVM的内存配置。理解HotSpot和其他虚拟机在实现和命名约定的不同也很重要。

IBM JVM 内存

IBM 虚拟机 内存分为2个区域:
• Java堆 Heap (年轻空间和年老空间)
• 本地堆(C-Heap)

这是他们的分析:

 

内存空间 启动参数和调整方法 监控方式 描述
Java 堆 -Xmx (最大堆容量)
-Xms (最小堆容量)
– verbose GC
– JMX API
– IBM 监控工具

EX:
-Xmx1024m
-Xms1024m

GC 策略Ex:
-Xgcpolicy:gencon
(使gencon GC 策略生效)

-verbose GC
– JMX API
– IBM监控工具IBM Java 堆通常分为年轻代和
年老代(YoungGen, OldGen).

年轻代 GC 策略 (联合了并发和分代GC)
通常用于Java EE 平台,为了最小化
GC暂停时间。本地堆 (C堆)不支持直接配置
对于32位虚拟机,C堆容量
= 4 Gig – Java堆

对于64位虚拟机,C堆容量 =
物理服务器总内存 & 虚拟内存
– Java堆

– svmon 命令C堆用来保存class元数据
对象,包括库文件,其他
JVM以及第三方本地代码对象。
也许你也注意到,IBM的虚拟机是没有持久代的。持久代仅用于HotSpot虚拟机。IBM虚拟机是用本地堆保存相关数据的Class元数据。
Oracle也开始打算将持久代从HotSpot里去掉,我们在接下来的部分会讨论。

Oracle JRockit JVM 内存

JRockit 虚拟机内存分为2个部分:
• Java堆(年轻代和老年代)
• 本地内存空间(Class池,C堆,线程…)

 

内存空间 启动参数和调整方法 监控方式 描述
Java 堆 -Xmx (最大堆容量)
-Xms (最小堆容量)

EX:
-Xmx1024m
-Xms1024m-verbose GC
– JMX API
– JRockit Mission
Control 工具集

JRockit Java堆通常分为年轻代
(短寿命对象)和年老代(长生命周期对象)。

本地内存空间不支持直接配置。

对32位虚拟机,本地内存空间容量
= 2-4 Gig – Java堆

** 依据你操作系统的不同,进程
大小限制 2 GB, 3 GB 或 4 GB
**

对64位虚拟机,本地内存空间容量
= 物理机总内存 &虚拟内存– Java堆

– 在Windows和Linux上
检查总进程大小

– Solaris & Linux 的
pmap 命令行

– JRockit JRCMD 工具

JRockit本地内存空间用
于存储Class元数据,线程
以及各种对象如库文件,
其他JVM和第三方本地代码对象。
和IBM虚拟机类似,JRockit也没有持久代,它使用本地堆存储相关对的Class元数据。

JRockit倾向于用更多的本地内存达到更好的性能。它没有解释模式,只有编译模式,由于它多了本地内存,和同等大小的Sun JVM相比,进程需要的大小通常会大好几百M 。但这不是一个大问题,除非你使用32位的JRockit并加上很大堆空间。这种方式下,对于JRockit(对于32位虚拟机来说,堆越大留个本地堆的就越小)来说,OutOfMemoryError的危险性归咎于本地堆消耗过高 。

HotSpot和JRockit的提供商Oracle的策略,是将这2个虚拟机合成一个,并且包含2个的优点和特性。这也使得JVM调优变得简单,因为未能理解这2个虚拟机的不同会导致错误的调优建议和性能问题。

译者介绍:
梅小西
Java工程师,关注JVM,并发编程,喜欢研究Python,Scala,Golang等。

时间: 2024-12-12 15:03:44

《JVM故障诊断指南》之1 —— JVM概览与介绍的相关文章

《JVM故障诊断指南》之3 —— Java 线程: JVM持有内存的分析

前面我们已经讨论过JVM里不同的堆空间,这节我们会给你提供教程,是关于如何从你的活动的应用Java线程中确定它持有多少堆空间,以及在哪里占用.这里有个来自Oracle Weblogic 10.0生产环境的真实案例,它能使你更好的理解分析过程. 我们也会演示这种情况,过多的垃圾收集或者堆空间内存占用问题并不总是由于真实的内存泄露引起,也可能是由于线程执行模型问题和太多的短生命对象引起. 后台 Java线程是JVM基础的一部分.你的Java堆空间内存占用不仅仅是由于静态的和长生命的对象导致,还有可能

《JVM故障诊断指南》之2 —— 调整合适的Java堆大小的技巧

原文链接 原文作者:Byron Kiourtzoglou 翻译:梅小西(904516706) 在生产系统上决定合适的Java堆大小不是一个容易的操作.许多性能问题的发生都是由于不恰当的Java堆容量的错误调整.这部分将从介绍一些技巧作为开头,它能帮助你在当前的或者新的生产系统上决定最佳的Java堆大小.其中一些技巧对预防OutOfMemoryError问题和内存泄露方面也同样有用. 请注意这些技巧是倾向于"帮助你"决定合适的Java堆大小.因为每一个IT环境都不相同,实际上你是处于最好

《JVM故障诊断指南》之4 —— Java 8:从持久代到metaspace

原文链接 原文作者:Byron Kiourtzoglou 翻译:梅小西(904516706) Java 8介绍了一些新语言以及运行时新特点.其中一个特点便是完全移除了持久代(PermGen),自从Oracle公司发布了JDK1.7后就已经宣布了这个决定.还有比如内部字符串,从JDK1.7开始就从持久代移除了,JDK8的发布彻底废除了它.在这个部分,我们会讨论持久代的继任者:Metaspace. 当执行一个Java程序并出现了"泄露"类元数据对象时我们会比较HotSpot 1.7和Hot

如何从 Classic JVM 迁移到 IBM J9 JVM

简介 从 IBM i 7.1 开始,IBM Classic Java Virtual Machine 不再被 IBM i 支持了.IBM Technology for Java Virtual Machine(又名 IBM J9 JVM)成为了唯一被支持的 JVM.这篇文章旨在阐述这两种 JVM 的区别,同时帮助用户和开发人员把他们的应用程序从 Classic JVM 移植到 J9 JVM.在 IBM i 上,所有版本的 Java 开发包(JDK)都以 Java 许可程序的 option 的形式

了解Java虚拟机JVM的基本结构及JVM的内存溢出方式_java

JVM内部结构图 Java虚拟机主要分为五个区域:方法区.堆.Java栈.PC寄存器.本地方法栈.下面 来看一些关于JVM结构的重要问题. 1.哪些区域是共享的?哪些是私有的? Java栈.本地方法栈.程序计数器是随用户线程的启动和结束而建立和销毁的, 每个线程都有独立的这些区域.而方法区.堆是被整个JVM进程中的所有线程共享的. 2.方法区保存什么?会被回收吗? 方法区不是只保存的方法信息和代码,同时在一块叫做运行时常量池的子区域还 保存了Class文件中常量表中的各种符号引用,以及翻译出来的

JVM必备指南(转)

本文由 ImportNew - xiafei 翻译自 anturis.欢迎加入翻译小组.转载请见文末要求. 简介 Java虚拟机(JVM)是Java应用的运行环境,从一般意义上来讲,JVM是通过规范来定义的一个虚拟的计算机,被设计用来解释执行从Java源码编译而来的字节码.更通俗地说,JVM是指对这个规范的具体实现.这种实现基于严格的指令集和全面的内存模型.另外,JVM也通常被形容为对软件运行时环境的实现.通常JVM实现主要指的是HotSpot. JVM规范保证任何的实现都能够以同样的方式解释执

JVM深入学习笔记六-JVM类加载

类加载过程 主要分为了 加载->链接(验证->准备->解析)->初始化->使用->卸载这几个阶段. 加载 三件事 1. 通过类的权限定名称来获取定义此类的二进制字节流(可以是文件,网络,数据库,动态等等等等) 2. 把类的结构放在方法区中 3. 创建Class对象作为访问入口 验证 主要包括了字节码验证,元数据验证(这部分在编译期间基本上避免了),类文件格式验证. 准备 包括了内存分配和类变量(static)初始值的设定,以及常量池的写入. 解析 主要是解析符号引用和直

jvm 垃圾回收 分代-JVM垃圾回收关于New Generation为什么分为三个区域的疑问

问题描述 JVM垃圾回收关于New Generation为什么分为三个区域的疑问 最近打算写一个分代垃圾回收,我打算在New Generation中分为两个区域,即只有 from区域 跟 to区域,但是最近查看了好多关于JVM的分代垃圾机制的文章,JVM在New Generation中分为三个区域,即Eden.from.to三个区域,好多文章介绍Eden都是该区域是一整块连续的堆,加速了分配的速度,但是我想问的是,如果只分为两个区域,每次从from拷贝到to后,to区域剩下的空间也是连续的,分配

JVM深入学习笔记七-JVM执行

运行时栈帧 栈帧( 局部变量表(基本数据类型,对象引用,returnAddress类型 ), 操作数栈 , 动态链接 , 方法返回地址 ) 局部变量表 以Slot为最小的单位.用来存放32位以内的数据类型.像long,double需要连续的两个Slot 局部变量从0位开始会每一个index对应一个变量的值0一般是this Slot可以改变,当程序计数器指针超出Slot的作用域(用{}指定)的时候则这个Slot就能够复制给其他人了. 垃圾回收的时候Slot会影响GC的行为,比如: public c