傻瓜式jvm基础学习

Qjvm调优是在做什么?

A:通过修改jvm参数和更换合适的垃圾回收器从而达到提高垃圾回收效率、降低停顿时间,提高系统的吞吐量和响应速度。

  从上面的问答中可以得到两个概念,jvm参数、垃圾回收器。

 

 

 

程序计数器

   存储当前线程正在执行的Java方法的字节码指令地址的内存区域,作为一个指示器使用,不会进行内存分配,因此不存在内存溢出的问题。

由于程序计数器是线程私有的,每个线程都有独立的程序计数器。这确保了在多线程环境下,线程切换后能够正确地恢复到上一个线程执行的位置。程序计数器在线程切换时起到了保持状态的重要作用。

Java虚拟机栈

  采用栈的数据结构来管理方法调用中的基本数据,先进后出(First In Last Out,每一个方法的调用使用一个栈帧(Stack Frame)来保存,虚拟机栈种保存着方法的局部变量、操作数栈(虚拟机在执行指令过程中用来存放临时数据的一块区域)、动态链接、方法返回地址(方法正常退出或异常退出的定义)和一些附加信息;局部变量的数量会影响到栈的深度

每个线程都会创建一个虚拟机栈,是线程私有的。栈的生命周期和线程同步一致,当线程线程结束,该虚拟机栈也就销毁了。

本地方法栈

  本地方法就是Java程序调用非Java代码的接口,它的实现不是由Java语言实现。当Java程序需要和外间需要交互时,就可以选择使用本地方法

     本地方法栈(Native Method Stack)用于本地方法的调用,线程私有,它允许被实现成固定大小或是可动态扩展的内存大小。程序使用本地方法栈的具体做法是:在本地方法栈中登记native方法,在执行引擎执行时加载本地方法库。当某个线程调用一个本地方法时,它就进入了一个全新的且不受虚拟机限制的世界,它和虚拟机拥有同样的权限。

  HotSpot直接将本地方法栈和虚拟机栈合二为一。

堆区

 

 

  堆是一种动态内存分配机制,用于存储在程序运行过程中创建的对象。它是线程共享的,堆中的对象都需要考虑线程安全问题;存放引用数据类型的数据和new出来的的对象。

      Jdk8后在逻辑上可以将堆区划分为新生代和老年代。新生代又可以划分为伊甸园区与幸存者区之间发生的内存整理行为是MinorGC,老年代发生的内存整理行为是MajorGC,整理堆区和方法区内存的行为是FullGC。

  堆内存的大小可以在运行时进行调整,以满足程序的需求。调整过程涉及到如下三个概念;used指的是当前已使用的堆内存,totaljava虚拟机已经分配的可用堆内存,maxjava虚拟机可以分配的最大堆内存。

  在 Java 中,堆内存的分配和管理由垃圾回收器(Garbage Collector,简称 GC)负责。当对象不再被引用时,GC 会自动回收其占用的内存空间。

  Java服务端程序开发时,建议将-Xmx和-Xms设置为相同的值,这样在程序启动之后可使用的总内存就是最大内存,而无需向java虚拟机再次申请,减少了申请并分配内存时间上的开销,同时也不会出现内存过剩之后堆收缩的情况

  默认的新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ) , 即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域, Edem 和俩个 Survivor 区域比例是 = 8 : 1 : 1 ( 可以通过参数 – XX:SurvivorRatio 来设定 ) ,但是 JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以 无论什么时候,总是有一块 Survivor 区域是空闲着的。

方法区

 

 

   用于存储类型信息、方法信息、常量、及时编译器编译后的缓存代码。方法区与Java堆一样,是各个线程共享的内存区域,并且在JVM启动时被创建,物理内存空间可以不连续,随着JVM的关闭而释放‌。

    JDK 7以前,习惯上把方法区称为永久代(习惯上),而到了JDK8,废弃了永久代的概念,改用与JRockitJ9一样在本地内存中实现的元空间(Metaspace)来代替。这两个最大的区别就是:元空间不在虚拟机设置的内存中,而是使用本地内存。

  jdk8 及之后使用参数 -XX:MetaspaceSize和-XX:MaxMetaspaceSize 来指定元空间的初始分配空间与最大可分配空间。在windows平台下,初始元空间的默认可分配空间是 21M ,最大可分配空间参数值为 -1(-1表示不限制)。

  如果不指定元空间可分配最大内存空间,极端情况下虚拟机会耗尽所有的可用系统内存,如果元空间区发生溢出,虚拟机会抛出异常:OutOfMenoryErrorMetaspace

 设置jvm内存的常用参数

参数类型

参数举例

备注

堆最大值(max

-Xmx6M

Xmx必须大于 2 MB,默认单位为字节(必须是1024的倍数)也可是指定单位k(K)m(M)g(G)

堆初始值(total)

-Xms6M

Xms必须大于1MB,默认单位为字节(必须是1024的倍数)也可是指定单位k(K)m(M)g(G)

Young区大小

-Xmn52M

 默认单位为字节,也可是指定单位k(K)、m(M)、g(G),GC操作在Young区比在其他区更频繁。如果Young区的规模太小,那么将进行大量的小型垃圾收集。如果大小太大,则只会执行完整的垃圾收集,这可能需要很长时间才能完成。Oracle建议将Young区的堆大小保持在总堆大小的一半到四分之一之间

元空间的初始分配空间(MetaspaceSize)

-XX:MetaspaceSize=128M

 设置元空间的大小,默认大小取决于平台.当到达设定值之后会触发FULLGC,如果设置为和MaxMetaspaceSize一样大,就不会FULLGC,但是对象也无法回收。

元空间的最大可分配空间(MaxMetaspaceSize)

-XX:MaxMetaspaceSize=512M

 设置元空间的最大内存量。默认情况下,大小不受限制。

Java虚拟机栈

-Xss128K

默认单位为字节(必须是1024的倍数)也可是指定单位k(K)m(M)g(G)栈的大小直接决定了函数调用的最大可达深度,设置的值超过默认最大或者最小时设置失效。一般大小控制在1M之内

 

 

 

 jvm参数模板

复制代码
-Xms1g    #  堆的初始值
-Xmx1g    #  堆的最大值
-Xss256k  #  栈大小
-XX:MaxMetaspaceSize=512m            #  元空间的最大值
-XX:+DisableExplicitGC               #  禁止在代码中使用System.gc()
-XX:+HeapDumpOnOutOfMemoryError      #  发生OutOfMemoryError错误时,自动生成hprof内存快照文件
-XX:HeapDumpPath=/opt/logs/my-service.hprof    #   指定hprof文件的输出路径
-XX:+PrintGCDetails     #   打印GC详细信息
-XX:+PrintGCDateStamps  #   GC时打印时间戳
-Xloggc:文件路径         #   GC日志生产路径
复制代码
JDK9及之后 使用 -Xlog:gc*:file=文件路径,代替了 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:文件路径

Jdk8常用的垃圾回收器

垃圾回收器

简介

目标

启用参数

适用场景

‌Serial收集器

Serial收集器是单线程的,在进行垃圾回收时会暂停所有用户线程,直到回收结束

响应速度优先

-XX:+UseSerialGC

单核处理器或客户端模式下的虚拟机

‌ParNew收集器‌‌

ParNewSerial收集器的多线程版本。它主要用于新生代垃圾回收,老年代则使用Serial Old

响应速度优先

-XX:+UseParNewGC

适用于多核处理器server模式

‌Parallel Scavenge收集器‌‌

这是一个并行多线程收集器,Parallel Scavenge收集器可以与Serial OldParallel Old搭配使用

吞吐量优先

-XX:+UseParallelGC

适用于服务端模式,适合响应时间要求不高的应用场景

‌CMSConcurrent Mark Sweep)收集器‌‌

这是一种并发收集器。CMS收集器在垃圾回收时允许用户线程继续执行,但它在处理老年代时需要依赖新生代的收集器,如ParNew

响应速度优先

-XX:+UseConcMarkSweepGC

适用于追求低延迟的应用,例如互联网网站或者bs系统

‌G1Garbage-First)收集器‌‌

G1收集器旨在平衡吞吐量和停顿时间。G1将堆内存划分为多个区域,并优先回收垃圾最多的区域,减少停顿时间

响应速度优先

-XX:+UseG1GC

适用于大内存服务器和复杂应用

 

 

 

 

 

 

垃圾回收器的组合关系

由于垃圾回收器分为年轻代和老年代,除了G1之外其他垃圾回收器必须成对组合进行使用。

 

posted @   干瘪咸鱼  阅读(7)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示