JVM--一文精通

news2024/12/24 3:08:52

调整JVM堆内存

在确定JVM堆内存大小时,需要考虑以下因素:

  1. 应用程序的内存需求。
  2. 操作系统和其他应用程序所需的内存。
  3. JVM的运行参数和GC算法。

根据通常的经验,可以将JVM最大堆内存设置为操作系统可用内存的约70%。也就是说,在16GB的机器上,建议将JVM堆内存设置为11GB左右。这样做可以确保一定的空闲内存供操作系统和其他应用程序使用,并且给JVM留出足够的空间来处理应用程序的内存需求。

当然,实际的情况可能因应用程序的特殊性质而异。如果应用程序需要更多的内存,那么可以相应地增加JVM堆内存大小。但是,要注意不要设置过大,否则可能会导致频繁的Full GC和长时间的停顿。

jvm的运行参数有哪些,如何调整

JVM的运行参数根据作用可以分为以下几类:

  1. 堆内存相关参数:包括-Xmx、-Xms、-XX:NewRatio、-XX:SurvivorRatio等,用于设置JVM堆内存大小以及新生代和老年代之间的比例等。

  2. GC相关参数:包括-XX:+UseG1GC、-XX:+UseConcMarkSweepGC、-XX:+UseParallelGC等,用于选择垃圾回收算法以及调整垃圾回收的行为。

  3. 线程相关参数:包括-XX:ParallelThreads、-XX:ConcGCThreads等,用于设置并发线程数以及并发GC的线程数。

  4. 类加载相关参数:包括-XX:PermSize、-XX:MaxPermSize、-XX:MetaspaceSize、-XX:MaxMetaspaceSize等,用于设置永久代或元空间的大小。

可以使用命令行方式或者配置文件方式来设置JVM运行参数。常用的命令行参数有:

  1. -Xmx:设置JVM最大堆内存大小。
  2. -Xms:设置JVM初始堆内存大小。
  3. -XX:PermSize:设置永久代大小。
  4. -XX:MaxPermSize:设置最大永久代大小。
  5. -XX:+UseG1GC:启用G1垃圾回收器。
  6. -XX:+PrintGCDetails:输出详细的GC信息。
  7. -XX:ThreadStackSize:设置线程栈大小。

 命令行:

java -Xmx4g -Xms2g -jar myapp.jar
对于较为复杂的应用程序,可以将JVM运行参数写入配置文件中,例如在Tomcat服务器中,可以在catalina.sh或catalina.bat脚本中添加以下内容:

JAVA_OPTS="-server -Xms2g -Xmx4g -XX:PermSize=256m -XX:MaxPermSize=512m"
export JAVA_OPTS


什么时候需要设置线程栈的大小

Java虚拟机中的每个线程都有一个私有的线程栈,用于存储本地方法栈、操作数栈、局部变量表等信息。默认情况下,每个线程栈的大小为1MB,可以通过设置命令行参数或者JVM选项来调整。

通常需要调整线程栈的大小是在以下场景:

  1. 栈溢出:如果线程使用的栈空间不足,就会抛出StackOverflowError异常。这通常发生在递归调用或者方法调用深度较大的情况下。可以通过增加线程栈的大小来避免栈溢出的问题。

  2. 内存占用:线程栈的大小也会影响应用程序的内存占用。如果创建了大量的线程,那么默认的线程栈大小可能会导致过多的内存占用。可以通过减小线程栈的大小来降低内存占用。

  3. 系统资源:线程栈的大小还会影响系统资源的使用。如果创建了过多的线程,并且每个线程都使用较大的栈空间,这可能会导致系统资源的浪费和效率下降。可以通过调整线程栈的大小来优化系统资源的使用。

需要注意的是,调整线程栈的大小可能会影响应用程序的性能和稳定性。如果线程栈的大小设置过小,可能会导致栈溢出和应用程序崩溃;如果线程栈的大小设置过大,可能会消耗过多的内存和系统资源。因此,在调整线程栈大小时需要综合考虑应用程序的需求和系统资源的情况,并进行测试和优化。

G1垃圾回收器限制

  1. 物理内存限制:G1垃圾回收器需要足够的物理内存才能发挥最佳性能。如果可用内存不足,则可能导致频繁的Full GC和长时间的停顿。

例如,在一个运行大型应用程序的服务器上,如果分配给Java进程的内存较小,那么G1垃圾回收器可能无法高效地工作,因为它需要足够的物理内存来执行标记、整理和压缩等操作。

  1. 启动时间延迟:G1垃圾回收器需要在启动时建立全局的Heap区域,这会导致较长的启动时间延迟。

例如,在一个需要快速启动的应用程序中,G1垃圾回收器可能不是最佳选择,因为它需要较长的启动时间来建立全局的Heap区域。

  1. 堆大小限制:G1垃圾回收器对堆内存的大小有一定的限制。通常建议将堆内存设置在4GB到32GB之间。如果堆内存过小,则可能导致频繁的Full GC;如果堆内存过大,则可能导致G1垃圾回收器无法高效地工作。

例如,在一个需要处理大规模数据集的应用程序中,如果堆内存设置过小,那么G1垃圾回收器可能无法有效地回收垃圾,导致频繁的Full GC和较长的暂停时间。

  1. 执行时间限制:G1垃圾回收器采用分代垃圾回收算法,因此在执行时会受到年轻代和老年代的大小限制。如果年轻代和老年代的大小比例不合适,则可能导致G1垃圾回收器效率下降。

例如,在一个需要处理大量短期请求的Web服务器上,如果设置了较小的年轻代空间,那么可能会导致G1垃圾回收器无法有效地回收短期对象,从而影响应用程序的性能。

  1. CPU资源限制:G1垃圾回收器需要占用一定的CPU资源来执行标记、整理和压缩等操作。如果CPU资源不足,则可能导致G1垃圾回收器无法高效地工作。

例如,在一个CPU资源有限的环境中,如果多个Java进程同时运行,并且使用了G1垃圾回收器,那么可能会导致CPU资源竞争和效率下降。

需要根据具体的应用情况来选择合适的垃圾回收算法以及调整相关的运行参数,以达到最佳的性能和可靠性。

为什么内存过小,会导致G1频繁的Full GC

在使用G1垃圾收集器时,内存过小可能会导致频繁的Full GC。G1垃圾收集器的主要任务是将堆空间划分为多个小块(region),并在每个小块中进行垃圾回收。Full GC是指在整个堆空间中进行垃圾回收的过程,而不仅仅是在某些小块中进行。

当内存过小时,G1垃圾收集器可能无法为对象保留足够的空间,因此需要更频繁地进行Full GC以便回收更多的空间。这会导致应用程序暂停,并且会降低应用程序的性能。

因此,在使用G1垃圾收集器时,请确保为其分配足够的内存,以避免频繁的Full GC。

g1和cms有什么区别

G1和CMS都是JVM中的垃圾回收器,用于回收不再使用的Java对象。它们之间的主要区别如下:

  1. 算法原理:G1采用的是基于区域的垃圾回收算法,而CMS则采用基于标记-清除的算法。

  2. 分代方式:G1将堆内存划分成多个大小相等的区域(Region),并根据每个区域的垃圾数量来决定回收顺序。CMS仅对老年代进行垃圾回收。

  3. 可预测性:G1垃圾回收器可以设置最大停顿时间,因此可以更好地控制垃圾回收期间的暂停时间。而CMS无法保证停顿时间。

  4. 内存占用:G1垃圾回收器可以动态调整堆内存大小,并且通常比CMS占用更少的内存。

  5. GC效率:G1垃圾回收器可以在多个CPU核心上并行执行标记、整理和压缩等操作,因此通常比CMS具有更高的GC效率。

总体而言,G1适用于需要高吞吐量和可预测性的应用程序,而CMS适用于需要快速响应时间和较低的暂停时间的应用程序。但是需要注意的是,对于特定的应用程序来说,并没有一种垃圾回收器可以适用于所有情况。因此,开发人员需要根据具体的应用场景和性能需求选择最合适的垃圾回收器。

从下图可以看出来,G1会做stop the world来进行筛选回收,但这个时间长短可以指定

G1原理图

 CMS原理图

jvm会在什么时候gc?什么时候full gc?

JVM(Java Virtual Machine)的垃圾回收机制是自动的,通常在以下情况下会进行垃圾回收:

  1. 空间规划阈值到达。JVM 在启动时会为 Java 堆分配一定大小的内存空间,当 Java 对象数量增加到一定程度时,就会触发 JVM 进行垃圾回收。

  2. 内存不足时。当 JVM 检测到 Java 堆没有足够的内存供应用程序使用时,就会启动垃圾回收机制。

  3. 调用 System.gc() 方法。虽然调用该方法并不能保证 JVM 立即执行垃圾回收,但它确实会增加 JVM 执行垃圾回收的可能性。

  4. 发生 OutOfMemoryError 错误。如果 JVM 检测到内存不足而且无法再分配更多内存时,就会抛出 OutOfMemoryError,此时 JVM 会启动垃圾回收机制。

Full GC 是一种特殊的垃圾回收机制,它会回收整个 Java 堆,包括 Eden 区、Survivor 区和老年代。Full GC 通常在以下情况下发生:

  1. 对象进入老年代时。当年轻代的 Eden 区、Survivor 区满了之后,对象会进入老年代,此时会触发 Full GC。

  2. 显式调用 System.gc() 方法。尽管显式调用 System.gc() 并不保证 JVM 立即执行 Full GC,但它确实会增加 JVM 执行 Full GC 的可能性。

需要注意的是,Full GC 是非常耗费资源的操作,因此建议在应用程序低峰期或者系统资源充足的情况下进行 Full GC。

类的加载过程:

1、当需要一个java类时,会通过classname,从classpath中查找到对应的class文件(加载过程通过双亲委派机制,直到顶层父加载器也找不到,就交由启动类加载器从磁盘里找到对应的class文件,并加载它),把class文件加载到方法区内,

2、class文件加载到内存后,jvm会对该类进行验证:检查正确性;准备:静态变量分配内存并设置默认值;解析:将符号引用变成直接引用(具体是指:常量池)

符号引用和直接引用

是常量池中的两种引用类型,符号是指具体描述符、直接引用是指通过符号可以直接定位到具体值

永久代、元空间、方法区:

永久代、元空间是实现方法区的一种方式,元空间再jdk8开始替换永久代,可以动态扩容

方法区主要存储类加载过程中的  类信息、常量、静态变量、静态方法。

static应用的对象,生命周期 等于 整个应用程序的生命周期

jvm堆内存

年轻代

老年代

如何判断对象是否可回收?

1、引用计数法,弊端 解决不了循环引用

2、可达性分析算法:通过虚拟机栈、本地方法区,方法去静态变量确定所有根节点,以这一组根节点作为起点,标记所有可达对象,没有被标记的就是可回收对象;

        注意可达性分析算法,计算可达遇到循环依赖依旧是通过计数法来解决循环标记的

垃圾回收算法

标记--清除 : 会造成内存碎片

复制算法:只利用了一般的内存空间,浪费资源

标记-整理:相对复制算法,比较耗时

在上面的基础上,诞生了分代回收法,根据对象的生命周期和特性,将堆内存分为新生代和老年代

新生代采用复制算法:8:1:1 S0 + 2个S1;老年代可以使用清楚或整理

有哪些垃圾回收器:

Serial收集器:单线程,stw、新生代:S0+2个S1/ 老年代也支持

Parallel收集器:stop the world:新生代老年代 

CMS收集器: 并发,stop the world时间短。老年代:标记清除、内存碎片

G1收集器:分块,没有年轻代和年老代之分,stw可配置,对内存要求高

jvm本地方法区:java的本地方法

jvm栈:虚拟机栈

栈帧是一种数据结构,即也就是队列,在虚拟机栈中

jvm为新线程创建虚拟机栈,执行方法时,jvm会会这个方法生成一个栈帧,将其推入前一个栈顶,开始执行这个方法的栈帧。jvm开始逐行执行这个方法,

执行完毕后,jvm弹出这个栈帧,返回到上一个栈帧继续执行,返回的值压入上一层的操作数栈中,当栈帧弹出后,虚拟机栈顶指向下一个栈帧,但线程执行完毕后,jvm会回收这个线程,并回收所创建的空间。

程序计数器

cpu有程序计数器,记录这上下指令的位置,记录这下一条执行的位置。

jvm线程也有程序计数器,

当一个方法被调用时,JVM 会将当前线程的程序计数器指向该方法的第一条字节码指令,并将该方法的栈帧推入虚拟机栈中。随着方法的执行,程序计数器会自动增加,指向下一条字节码指令,同时栈帧中的局部变量和操作数栈也会随之改变。当方法执行完毕后,该方法的栈帧从虚拟机栈中弹出,并且程序计数器会回到原来的值,继续执行调用该方法的方法。

就是说 jvm创建线程后,为其创建虚拟机栈和程序计数器,程序计数器记录着当前指令字节码的位置,并将方法压入栈顶,开始执行,执行过程中 程序计数器会不停的增加。

结合以上:new一个对象的过程

1、去方法区找class对象,如果没有双亲委派机制加载(从磁盘加载class文件字节流,load到方法区,开始 验证-准备(初始化静态)-解析(常量池符号引用-》直接引用:会加载所需依赖class)) 

2、找到之后,在堆中分配空间内存,创建对象

3、很大直接到老年代,不大的话就到S0,之后到S1,S2之后到到年老代

结合以上:方法是如何调用的

jvm创建线程后,为其创建虚拟机栈和程序计数器,程序计数器记录着当前指令字节码的位置,并将方法压入栈顶,开始执行,执行过程中 程序计数器会不停的增加。

JVM调优经验:

1、发现问题:访问很慢,经常堆溢出、栈溢出

2、堆溢出 需要考虑是否是大对象、内存空间分配不合理,对象产生较快

3、栈溢出 需要考虑是否死循环,导致调用递归过深,超过了jvm允许的最大深度,局部变量过多,超过了限制(1M)

4、借助一些监控工具,分析问题,适当调整相关内存大小,选择使用合适的回收器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/479596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kube-OVN组件

文章目录 介绍ovn架构kube-ovn架构kube-ovn数据流向软件版本及注意事项高可用部署安装kube-ovn运维查看Pod日志组件监控kubectl ko插件 网络相关 介绍 kube-ovn是基于ovn开发的。https://man7.org/linux/man-pages/man7/ovn-architecture.7.html ovn架构 组件说明&#xff1a…

PySide6/PyQT多线程之 信号与槽 / (Signal Slot)的高效利用

前言 PySide6/PyQT信号槽是一种事件处理方式,允许程序中的对象发送和接收信号。 在 PySide6/PyQT 精进的过程中,一定躲不开 信号和槽 这座大山,这是一个比较有意思的知识点: 初接触的看不懂,觉得复杂;看得…

【Linux】win10远程控制Linux服务器 - 内网穿透实现公网远程

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 前言 视频教程 1. ubuntu安装XRDP 2.局域网测试连接 3. Ubuntu安装cpolar内网穿透 4.cpolar公网地址测试访问 5.固定域名公网地址 [TOC] 转载自远程穿透文章:Wi…

Redis的两种持久化方案 RDB AOF

文章目录 1.RDB持久化1.1.执行时机1.2.RDB原理1.3.小结 2.AOF持久化2.1.AOF原理2.2.AOF配置2.3.AOF文件重写 3.RDB与AOF对比 Redis有两种持久化方案: RDB持久化AOF持久化 1.RDB持久化 RDB全称Redis Database Backup file(Redis数据备份文件&#xff09…

【三十天精通Vue 3】 第二十三天 Vue 3的错误处理详解

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 错误处理概览1. 错误处理的重要性2. Vue 3 中的错误…

EMS快递批量分析物流信息状况

众所周知“邮政快递”是在快递行业里面也是算一家行业龙头,中国邮政特快专递/EMS,邮政平邮小包,邮政挂件等,都是属于中国邮政集团,邮政速度快,价格也是比较实惠一家,所以很多产家或电商 、供应商…

大数据-玩转数据-FLINK快速上手

一、环境准备 ⚫系统环境为 Windows 10。 ⚫需提前安装 Java 11。 ⚫集成开发环境(IDE)使用 IntelliJ IDEA,具体的安装流程参见 IntelliJ 官网。 ⚫安装 IntelliJ IDEA 之后,还需要安装一些插件——Maven 和 Git。Maven 用来管理…

Java实现宿舍管理系统的设计与实现【附源码】

本科生毕业论文(设计) 宿舍管理系统的设计与实现 目 录 摘 要 I Abstract II 1 引言 1 1.1 研究背景 1 1.2 国内外研究现状 1 1.3 研究目的与意义 1 2 开发工具和相关技术 2 2.1 Eclipse 2 2.2 MySQL 2 2.3 Bootstrap 3 2.4 Tomcat 3 3 系统分析 3 3.1…

Java基础学习(11)

Java基础学习 一、集合进阶1.1 数据结构(树)1.1.1 二叉查找树1.1.2 二叉树的遍历 1.2 平衡二叉树树的演变 1.3 数据结构 ( 平衡二叉树 )左旋1.4 数据结构 ( 平衡二叉树 )右旋数据结构 (平衡二叉树)需要转的四种情况 1.5 红黑树添加节点规则 二、Set系列集…

基础算法(五):DFS、BFS与剪枝

前言 前面的基础算法笔记已经断更好久了,因为荔枝觉得还是得先学一下基础的数据结构知识之后才能更好的入门算法。在这篇文章中荔枝主要记录DFS和BFS的相关基础知识、答题的模板以及自己的一些浅薄理解,同样的也会涉及到相关的剪枝操作。 一、搜索算法概…

java基础学习-7

文章目录 异常小总结编译时异常和运行时异常小总结 异常在代码中的两个作用异常的方式JVM虚拟机默认处理异常的方式自己处理(捕获异常)灵魂四问抛出异常异常中的常见方法小总结小练习 自定义异常 File----路径File的概述和构造方法小总结 File的成员方法…

线性表之顺序表(C语言实现)

前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言初阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:讲解数据结构的入门知识,线性结构之顺序表. 金句分享:…

机器学习笔记 基于深度学习的边缘检测

一、Holistically-Nested Edge Detection 边缘检测是视觉工作中十分常用的技术,传统边缘检测已经包含了很多经典的诸如Canny、Robert等等,都是各有擅场,不过有一点问题,就是很多参数需要人工调试,所以深度学习研究人员提出了基于卷积神经网络的边缘检测算法。 即HED,该算…

uniapp拍照离线定位,获取图片信息,经纬度解析地址

✅作者简介: 我是痴心阿文,你们的学友哥,今天给大家分享uniapp拍照离线定位,获取图片信息,经纬度解析地址 📃个人主页:痴心阿文的博客_CSDN博客-Vue.js,数组方法,前端领域博主 🔥本文前言&#…

【数据结构】超详细之顺序表(利用C语言实现)

文章目录 前言一、顺序表是什么?二、顺序表的实现步骤 1.顺序表的初始化以及开辟空间2.实现顺序表的头插、尾插以及打印3.实现顺序表的头删、尾删以及打印4.实现顺序表的查找5.实现顺序表指定位置插入6.实现顺序表指定位置删除7.释放内存总结 前言 数据结构是一个程…

离散数学_九章:关系(3)

9.3 关系的表示 1、用集合表示关系2、用矩阵表示关系矩阵表示关系⭐集合上的关系矩阵 R 自反时 R 对称时 R 反对称时 ⭐确定关系合成的矩阵 3、用有向图表示关系有向图⭐从有向图中 确定关系具有的属性 自反性对称性反对称性传递性 本节及本章的剩余部分研究的所有关系均为二…

函数(详解)——C语言

Hello,友友们前段时间忙拖更了这么久,趁着五一假期好好卷上一波哈哈哈。好的,我们本期主要对C语言中的函数进行讲解。 1.什么是函数 在数学中也常常用到函数,但你对C语言中的函数有了解吗? 在C语言中函数是一段可重…

数据结构学习分享之单链表详解

数据结构第三课 1. 前言2. 链表的概念以及结构3. 链表的分类4.链表的实现4.1 初始化结构4.2 尾插函数4.3 尾删函数4.4 头插函数4.5 头删函数4.6 开辟新节点4.7 销毁链表 5. 单链表OJ题目6. 顺序表和链表的区别7. 总结 1. 前言 💓博主CSDN:杭电码农-NEO💓…

五年开发经验前端程序员,刚入职一个月就要离职,我来聊聊看法

最近有一个新来的同事,估计又要离职了吧。从他的工作经历来看,大概有5年的前端工作经验,但是头发看起来挺少的,不知道是工作加班导致的,看他的性格不太像是经常加班的。 他这个人就是我们公司人事面试的,虽…

操作系统——进程管理

0.关注博主有更多知识 操作系统入门知识合集 目录 0.关注博主有更多知识 4.1进程概念 4.1.1进程基本概念 思考题: 4.1.2进程状态 思考题: 4.1.3进程控制块PCB 4.2进程控制 思考题: 4.3线程 思考题: 4.4临界资源与临…