【IT专家】JVM调优系列:(二)JVM运行时数据区域

合集下载

记一次JVMFullGC(MetadataGCThreshold)调优经历

记一次JVMFullGC(MetadataGCThreshold)调优经历

记⼀次JVMFullGC(MetadataGCThreshold)调优经历记⼀次JVM Full GC (Metadata GC Threshold)调优经历⼀、背景:线上服务器内存使⽤超过90%,分析上⾯部署的各个服务的GC⽇志,发现有⼀个服务的JVM内存分配过⼤,使⽤率较低,有调优的空间,可以在不迁移服务或者不升级服务器配置的情况下,降低服务器内存占⽤。

JVM推荐配置原则:应⽤程序运⾏时,计算⽼年代存活对象的占⽤空间⼤⼩X。

程序整个堆⼤⼩(Xmx和Xms)设置为X的3 ~ 4倍;永久代PermSize和MaxPermSize设置为X的1.2 ~ 1.5倍。

年轻代Xmn的设置为X的1 ~ 1.5倍。

⽼年代内存⼤⼩设置为X的2 ~ 3倍。

JDK官⽅建议年轻代占整个堆⼤⼩空间的3/8左右。

完成⼀次Full GC后,应该释放出70%的堆空间(30%的空间仍然占⽤)。

观察线上发现2G的堆内存,Full GC之后的活跃对象才占⽤60M。

按照推荐设置JVM内存只需要给⼏百M就好了。

所以决定改成1G,既能够降低服务器内存占⽤,也预留了⾜够的业务增长空间。

在这个过程中,发现如下⼏个问题:GC⽇志没有时间显⽰,看起来很不⽅便GC⽇志没有滚动,时间久了,⽇志⽂件较⼤GC⽇志中存在⼤量Full GC (Metadata GC Threshold)显然第三个问题最为严重。

我们知道,元数据区主要是⽤来存储类的元数据的。

⼀般来讲,类加载完成之后,⼤⼩应该是⽐较稳定的,不会有太⼤变动。

所以可以判断,这么频繁的Full GC (Metadata GC Threshold),肯定是哪⾥出问题了。

但是我们⼀步⼀步来解决问题,⽽且GC⽇志不够详细也影响我们定位问题。

⼆、优化GC⽇志打印⾸先复习⼀下JVM的GC⽇志打印的启动参数。

详见-verbose:gc同-XX:+PrintGC-XX:+PrintGC最简单的 GC 参数会打印 GC 前后堆空间使⽤情况以及 GC 花费的时间-XX:+PrintGCDetails打印GC的详细信息,会打印 youngGC FullGC前后堆【新⽣代,⽼年代,永久区】的使⽤情况以及 GC 时⽤户态 CPU 耗时及系统CPU 耗时及 GC 实际经历的时间-XX:+PrintGCTimeStamps打印CG发⽣的时间戳,从应⽤启动开始累计的时间戳-XX:+PrintGCDateStamps打印GC发⽣的时刻,所处⽇期时间信息-Xloggc:gc.log指定GC log的位置,以⽂件输出-XX:+PrintHeapAtGC每⼀次GC前和GC后,都打印堆信息。

《Java性能调优指南》

《Java性能调优指南》

《Java性能调优指南》随着互联网的飞速发展,Java作为一种重要的编程语言,被越来越广泛地应用于各个领域。

但是,Java程序的性能问题也随之出现。

如何调优Java 程序的性能,成为了每个开发人员需要解决的难题。

本文将为大家介绍Java性能调优的指南。

一、JVM参数设置JVM(Java虚拟机)参数设置是Java性能调优的关键。

JVM有众多的参数,不同的参数设置会对Java程序的性能产生不同的影响。

常用的JVM参数设置包括以下几个方面:1. 内存设置内存是Java程序的一大瓶颈。

如果内存设置不合理,会导致Java程序频繁地进行垃圾回收,造成程序的延迟和不稳定。

在设置内存参数时需要注意以下几点:- -Xmx: 最大堆内存,设置合理的最大堆内存大小可以减少JVM的垃圾回收次数,提高程序性能。

- -Xms: 初始堆内存,设置合理的初始堆内存大小可以加快程序启动时间,提高程序性能。

- -XX:NewRatio: 新生代与老年代的比例,如果设置得当,可以减少垃圾回收的次数。

通常新生代的大小为总堆容量的1\/3或1\/4,老年代的大小为总堆容量的2\/3或3\/4。

2. 垃圾回收设置垃圾回收是Java程序中必不可少的一部分。

合理的垃圾回收参数设置可以提高程序性能。

常用的垃圾回收参数设置包括以下几点:- -XX:+UseParallelGC: 使用并行GC,适用于多核CPU。

- -XX:+UseConcMarkSweepGC: 使用CMS GC,适用于大型Web应用程序。

- -XX:+UseG1GC: 使用G1 GC,适用于大内存应用程序。

3. JIT设置JIT(即时编译器)是Java程序中非常重要的一部分。

合理的JIT参数设置可以提高程序的性能。

常用的JIT参数设置包括以下几点:- -XX:+TieredCompilation: 启用分层编译,可以提高程序启动时间和性能。

- -XX:CompileThreshold: JIT编译阈值,设置JIT编译的最小方法调用次数,可以提高程序性能。

Java虚拟机JVM各调优参数说明

Java虚拟机JVM各调优参数说明

Java虚拟机JVM各调优参数说明Java虚拟机(JVM)是Java程序运行的环境,它负责将Java源代码编译为字节码,并在运行时执行这些字节码。

JVM的性能对于Java应用程序的性能至关重要。

为了优化JVM的性能,我们可以通过调整一些参数来改变其行为。

下面是JVM各调优参数的详细说明。

1. -Xms和-Xmx:这两个参数用于设置JVM的初始堆大小和最大堆大小。

初始堆大小表示JVM在启动时申请的内存大小,最大堆大小表示JVM所能申请的最大内存大小。

可以使用以下命令设置初始堆大小为1GB,最大堆大小为2GB:-Xms1g -Xmx2g。

2. -XX:NewSize和-XX:MaxNewSize:这两个参数用于设置新生代的初始大小和最大大小。

新生代是JVM堆的一部分,用于存放新创建的对象。

可以使用以下命令设置新生代的初始大小为256MB,最大大小为512MB:-XX:NewSize=256m -XX:MaxNewSize=512m。

3. -XX:SurvivorRatio:这个参数用于设置新生代中Eden区和Survivor区的比例。

Eden区是新对象的分配区域,Survivor区是用于存放幸存的对象的区域。

可以使用以下命令设置Eden区和Survivor区的比例为8:1:-XX:SurvivorRatio=84. -XX:MaxTenuringThreshold:这个参数用于设置对象在Survivor区中的最大年龄。

当对象在Survivor区中存活的时间超过这个阈值时,它将被晋升到老年代。

可以使用以下命令设置最大年龄为15:-XX:MaxTenuringThreshold=155. -XX:PermSize和-XX:MaxPermSize:这两个参数用于设置永久代的初始大小和最大大小。

永久代用于存放类的元数据、静态变量和常量池等信息。

可以使用以下命令设置永久代的初始大小为128MB,最大大小为256MB:-XX:PermSize=128m -XX:MaxPermSize=256m。

jvm时区参数

jvm时区参数

JVM时区参数1. 什么是JVM时区参数JVM(Java虚拟机)时区参数是指用来设置Java应用程序运行时所使用的时区的配置参数。

时区是指地球上不同地区在时间上的差异,由于地球的自转和公历的使用,不同地区的时间会有所不同。

Java应用程序通常需要处理时间相关的业务逻辑,因此需要通过设置时区参数来确保时间的准确性和一致性。

2. JVM时区参数的作用JVM时区参数的作用是告诉Java虚拟机使用哪个时区来解析和格式化日期和时间。

在Java中,日期和时间的处理是通过java.util.Date、java.util.Calendar、java.time.LocalDate等类来实现的。

这些类在解析和格式化日期和时间时都依赖于时区信息。

如果没有正确设置时区参数,就可能导致日期和时间的处理出现错误。

3. JVM时区参数的配置方式JVM时区参数可以通过命令行参数或配置文件来进行配置。

3.1 命令行参数可以使用以下命令行参数来配置JVM的时区参数:-Duser.timezone=<timezone>其中,<timezone>是时区的标识符,例如Asia/Shanghai表示中国上海时区,America/New_York表示美国纽约时区。

例如,要将JVM的时区设置为中国上海时区,可以使用以下命令:java -Duser.timezone=Asia/Shanghai YourApplication3.2 配置文件JVM时区参数也可以通过配置文件来配置。

可以在jvm.options或java.security文件中添加以下配置:-Duser.timezone=<timezone>4. 常用的时区标识符Java中支持的时区标识符非常丰富,包括了世界上几乎所有的时区。

以下是一些常用的时区标识符:•Asia/Shanghai:中国上海时区•Asia/Tokyo:日本东京时区•Europe/London:英国伦敦时区•America/New_York:美国纽约时区•America/Los_Angeles:美国洛杉矶时区可以通过Java的ZoneId类来获取所有支持的时区标识符:Set<String> timeZones = ZoneId.getAvailableZoneIds();5. JVM时区参数的注意事项在配置JVM时区参数时,需要注意以下几个问题:5.1 时区参数的优先级JVM时区参数的优先级高于操作系统的默认时区。

JVM内存区域的划分(内存结构或者内存模型)

JVM内存区域的划分(内存结构或者内存模型)

JVM内存区域的划分(内存结构或者内存模型)运⾏时数据区域:根据 JVM 规范,JVM 内存共分为虚拟机栈、堆、⽅法区、程序计数器、本地⽅法栈五个部分。

程序计数器(线程私有): 是当前线程所执⾏的字节码的⾏号指⽰器,每条线程都要有⼀个独⽴的程序计数器,这类内存也称为“线程私有”的内存。

正在执⾏java⽅法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。

如果还是Native⽅法,则为空。

这个内存区域是唯⼀⼀个在虚拟机中没有规定任何OutOfMemoryError情况的区域。

Java虚拟机栈(线程私有): 也是线程私有的。

每个⽅法在执⾏的时候会创建⼀个栈帧,存储了局部变量表,操作数栈,动态连接,⽅法返回地址等。

每个⽅法从调⽤到执⾏完毕,对应⼀个栈帧在虚拟机栈中的⼊栈和出栈。

通常所说的栈,⼀般是指虚拟机栈中的局部变量表部分。

局部变量表所需的内存在编译期间完成分配。

如果线程请求的栈深度⼤于虚拟机所允许的深度,则StackOverflowError。

如果虚拟机栈可以动态扩展,扩展到⽆法申请⾜够的内存,则OutOfMemoryError。

本地⽅法栈(线程私有): 和虚拟机栈类似,主要为虚拟机使⽤到的Native⽅法服务。

也会抛出StackOverflowError和OutOfMemoryError。

Java堆(线程共享): 被所有线程共享的⼀块内存区域,在虚拟机启动时创建,⽤于存放对象实例。

堆可以按照可扩展来实现(通过-Xmx和-Xms来控制) 当堆中没有内存可以分配给实例,也⽆法再扩展时,则抛出OutOfMemoryError异常。

⽅法区(线程共享): 被所有线程共享的⼀块内存区域。

⽤于存储已被虚拟机加载的类信息,常量,静态变量等。

这个区域的内存回收⽬标主要针对常量池的回收和对类型的卸载。

当⽅法区⽆法满⾜内存分配需求时,则抛出OutOfMemoryError异常。

在HotSpot虚拟机中,⽤永久代来实现⽅法区,将GC分代收集扩展⾄⽅法区,但是这样容易遇到内存溢出的问题。

jvm系列(二):JVM内存结构

jvm系列(二):JVM内存结构
没有直接设置老年代的参数,但是可以设置堆空间大小和新生代空间大小两个参数来间接控制。 老 年 代 空 间 大 小 =堆 空 间 大 小 -年 轻 代 大 空 间 大 小
从更高的一个维度再次来看JVM和系统调用之间的关系 方法区和对是所有线程共享的内存区域;而java栈、本地方法栈和程序员计 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
jvm系列(二): JVM内存结构
JVM内存结构
所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块 区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问题就会变的非常常见,了解JVM内存也是为了服务器出现性能问 题的时候可以快速的了解那块的内存区域出现问题,以便于快速的解决生产故障。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在 实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。
如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
在通过一张图来了解如何通过参数来控制各区域的内存大小
控制参数 -Xms设置堆的最小空间大小。 -Xmx设置堆的最大空间大小。 -XX:NewSize设置新生代最小空间大小。 -XX:MaxNewSize设置新生代最大空间大小。 -XX:PermSize设置永久代最小空间大小。 -XX:MaxPermSize设置永久代最大空间大小。 -Xss设置每个线程的堆栈大小。

JVM内存区域划分

JVM内存区域划分

JVM性能调优-JVM内存区域划分1.程序计数器(线程私有) 程序计数器(Program Counter Register),也有称作为PC寄存器。

保存的是程序当前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址),当CPU需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加1或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令。

也就是说是用来指示执行哪条指令的。

由于在JVM中,多线程是通过线程轮流切换来获得CPU执行时间的,因此,在任一具体时刻,一个CPU的内核只会执行一条线程中的指令,因此,为了能够使得每个线程都在线程切换后能够恢复在切换之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰,否则就会影响到程序的正常执行次序。

因此,可以这么说,程序计数器是每个线程所私有的。

在JVM规范中规定,如果线程执行的是非native方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是native方法,则程序计数器中的值是undefined。

由于程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。

异常情况:不存在2.Java栈(线程私有) Java栈也称作虚拟机栈(Java Vitual Machine Stack) Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表、操作数栈、指向当前方法所属的类的运行时常量池的引用、方法返回地址、额外的附加信息。

当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。

当方法执行完毕之后,便会将栈帧出栈。

因此可知,线程当前执行的方法所对应的栈帧必定位于Java栈的顶部。

局部变量表,用来存储方法中的局部变量(包括在方法中声明的非静态变量以及函数形参)。

jvm原理及性能调优

jvm原理及性能调优

jvm原理及性能调优JVM原理及性能调优。

JVM(Java Virtual Machine)是Java虚拟机的缩写,是Java程序运行的核心组件。

它负责将Java字节码文件解释成特定平台上的机器指令。

JVM的性能对于Java应用程序的运行效率和稳定性有着至关重要的影响。

因此,了解JVM的原理并进行性能调优是非常重要的。

首先,我们来了解一下JVM的基本原理。

JVM主要由类加载器、运行时数据区、执行引擎三部分组成。

类加载器负责将class文件加载到JVM中,并对类进行初始化、连接和加载。

运行时数据区包括方法区、堆、虚拟机栈、本地方法栈和程序计数器,它们分别用于存储类的结构信息、对象实例、方法调用、本地方法和线程执行的位置。

执行引擎负责执行字节码指令,将Java程序转换成机器代码。

了解了JVM的基本原理之后,我们需要关注JVM性能调优的相关内容。

JVM 性能调优主要包括内存管理、垃圾回收、JIT编译器优化和线程管理等方面。

在内存管理方面,我们可以通过调整堆内存大小、永久代大小、新生代和老年代的比例等参数来优化内存的使用。

合理的内存分配可以减少内存碎片,提高内存使用效率。

垃圾回收是JVM性能调优的重要一环。

通过调整垃圾回收器的类型、参数和触发条件,我们可以优化垃圾回收的效率,减少应用程序的停顿时间,提高系统的吞吐量。

JIT编译器是JVM的即时编译器,它负责将热点代码编译成本地机器代码,以提高程序的执行速度。

我们可以通过调整JIT编译器的参数来优化编译效率,提高程序的性能。

线程管理也是JVM性能调优的重要内容。

合理的线程调度和线程池的使用可以提高系统的并发性能,减少线程的竞争和阻塞,提高系统的吞吐量。

除了上述内容,我们还可以通过监控工具对JVM进行性能分析,找出程序的瓶颈,并针对性地进行优化。

常用的监控工具包括JVisualVM、JConsole、JProfiler 等。

总的来说,JVM的性能调优是一个复杂而又细致的工作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

本文由我司收集整编,推荐下载,如有疑问,请与我司联系JVM调优系列:(二)JVM运行时数据区域2015/07/01 1546
JAVA的JVM的内存模型大致可分为3个区:
 堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。

(class的目的是得到操作指令)
 2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
 栈区:
 线程在执行一个Java方法时候,它的PC寄存器总是指向下一条需要执行的指令,而它的Java栈则保存线程中Java方法的调用状态,比如: 它的局部变量、传入方法的参数、返回值、以及运算的中间结果等。

1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。

 本地方法栈:
 当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的本地方法栈。

本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,它和虚拟机拥有同样的权限(能力)。

 任何本地方法接口都会使用某种本地方法栈。

当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。

然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态链接并直接调用指定的本地方法。

 如果某个虚拟机实现的本地方法接口是使用C连接模型的话,那么它的本地方。

相关文档
最新文档