JVM你想了解的那些事儿

Megatron单机多卡Qwen2.5:pre-train+sft 英伟达:https://github.com/NVIDIA/Megatron-LM/releases/tag/core_r0.8.0阿里:https://github.com/alibaba/Pai-Megatron-Patch/releases/tag/v0.10.2。 阅读详情

学习JVM前 先思考一下一个对象被实例化的过程
https://www.hellojava.com/a/92881.html
带着疑问来开始学习JVM

什么是JVM

JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和 一个存储方法域。JVM 是运行在操作系统之上的,它与硬件没有直接的交互。
在这里插入图片描述

JVM作用

Java虚拟机就是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台上的机器指令执行。每一条Java指令,Java虚拟机规范中都有详细定义,如怎么取操作数,怎么处理操作数,处理结果放在哪里。

JVM特点:

1一次编译到处运行。
2自动内存管理
3自动垃圾回收功能

在这里插入图片描述
JVM的位置
在这里插入图片描述
在这里插入图片描述

JVM 运行过程:

我们都知道 Java 源文件,通过编译器,能够生产相应的.Class 文件,也就是字节码文件,而字节码文件又通过 Java 虚拟机中的解释器,编译成特定机器上的机器码 。
也就是如下:
① Java 源文件—->编译器—->字节码文件
② 字节码文件—->JVM—->机器码
每一种平台的解释器是不同的,但是实现的虚拟机是相同的,这也就是 Java 为什么能够跨平台的原因了 ,当一个程序从开始运行,这时虚拟机就开始实例化了,多个程序启动就会存在多个虚拟机实例。程序退出或者关闭,则虚拟机实例消亡,多个虚拟机实例之间数据不能共享。
在这里插入图片描述
在这里插入图片描述

JVM内存区域

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Java代码执行的流程:
在这里插入图片描述

JVM的生命周期:

虚拟机的启动
Java虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类是由虚拟机的具体实现指定的。
虚拟机的执行
·一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序。·程序开始执行时他才运行,程序结束时他就停止。
·执行一个所谓的Java程序的时候,真真正正在执行的是一个叫做Java虚拟机的进程。
虚拟机的退出
有如下的几种情况:·程序正常执行结束
程序在执行过程中遇到了异常或错误而异常终止
由于操作系统出现错误而导致Java虚拟机进程终止
某线程调用Runtime类或system类的exit方法,或 Runtime类的halt方法,并且Java安全管理器也允许这次exit或halt操作。
除此之外,JNI ( Java Native Interface)规范描述了用JNI
Invocation API来加载或卸载Java虚拟机时,Java虚拟机的退出情况。

内存结构概述:

在这里插入图片描述

JVM调优的位置:主要是堆
在这里插入图片描述

类加载器以及双亲委派机制

类加载器
在这里插入图片描述

类的加载过程 1:Loading

1.通过一个类的全限定名获取定义此类的二进制字节流
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3.在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口

2Linking

验证(Verify) :
目的在于确保class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
·主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。准备(Prepare) :
·为类变量分配内存并且设置该类变量的默认初始值,即零值。
·这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化;
这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
解析(Resolve) :
·将常量池内的符号引用转换为直接引用的过程。
·事实上,解析操作往往会伴随着JVM在执行完初始化之后再执行。
符号引用就是一组符号来描述所引用的目标。符号引用的字面量形式明确定义在《java虚拟机规范》的class文件格式中。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。
解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的CONSTANT Class info、CONSTANT Fieldref info、CONSTANT Methodref info等

3 Initialization

初始化:
·初始化阶段就是执行类构造器方法()的过程。
此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
构造器方法中指令按语句在源文件中出现的顺序执行。|
()不同于类的构造器。(关联:构造器是虚拟机视角下的( ) )若该类具有父类,JVM会保证子类的()执行前,父类的()已经执行完毕。
虚拟机必须保证一个类的 ()方法在多线程下被同步加锁。

双亲委派机制
在这里插入图片描述
双亲委派机制:
在这里插入图片描述
执行的时候报错,因为它会按照双亲委派机制来走,先逐级往上走,如果根加载器没有才往下走。
在这里插入图片描述
双亲委派机制讲的很详细

沙箱安全机制

可以大致了解一下,了解即可,主要是双亲委派机制
https://blog.youkuaiyun.com/qq_30336433/article/details/83268945?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162756867316780269891836%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162756867316780269891836&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~hot_rank-7-83268945.first_rank_v2_pc_rank_v29&utm_term=%E6%B2%99%E7%AE%B1%E5%AE%89%E5%85%A8%E6%9C%BA%E5%88%B6&spm=1018.2226.3001.4187

Native方法区

native :凡是带了native 关键字的,说明java的作用范围达不到了,回去调用底层c语言的库!会近入本地方法栈,调用本地方法本地按口JNI
JNI作用:扩展Java的使用,融合不同的编程语言为ava所用!最初:C、C++t。//Java诞生的时候C、C++横行,想要立足,必须要有调用c、C+的程序
它在内存区域中专门开辟了一块标记区域:Native Nethod Stack,登记 native方法/在最终执行的时候,加载本地方法库中的方法通过JNI
// Java程序驱动打印机,管理系统这些在使用的时候需要调用本地方法库,掌握即可,在企业级应用中较为少见!

PC寄存器

程序计数器:Program Counter Register
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计

方法区 (永久代)

Method Area方法区
方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间;
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关

在这里插入图片描述
在这里插入图片描述

栈

栈:又称栈内存,主管程序的运行,生命周期和线程同步;
线程结束,栈内存也就是释放,对于栈来说,不存在垃圾回收问题一旦线程结束,栈就Over!
每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
栈帧( Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、 方法返回值和异常分派( Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。
栈里边存储:8大基本类型+对象引用+实例的方法
在这里插入图片描述
本文下边也有对栈帧的详细描述

栈溢出的一个图解:死循环
在这里插入图片描述
在这里插入图片描述

每执行一个方法都会产生一个栈帧,程序正在执行的方法一定在栈的顶部如下图
在这里插入图片描述
栈里边具体怎么存:
在这里插入图片描述

堆

在这里插入图片描述

JVM运行时的内存

在这里插入图片描述

新生代

是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区。
Eden 区
Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老
年代)。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行
一次垃圾回收。
ServivorFrom
上一次 GC 的幸存者,作为这一次 GC 的被扫描者。
ServivorTo
保留了一次 MinorGC 过程中的幸存者。

MinorGC 在新生代中采用复制算法:

1:eden、servicorFrom 复制到 ServicorTo,年龄+1
首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不够位置了就放到老年区);
2:清空 eden、servicorFrom
然后,清空 Eden 和 ServicorFrom 中的对象;
3:ServicorTo 和 ServicorFrom 互换
最后,ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom区。

老年代

主要存放应用程序中生命周期长的内存对象。
老年代的对象比较稳定,所以 MajorGC 不会频繁执行。在进行 MajorGC 前一般都先进行了一次 MinorGC,使得有新生代的对象晋升入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。
MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的时候,就会抛出 OOM(Out of Memory)异常。

永久代

指内存的永久保存区域,主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被放入永久区域,它和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。

JAVA8 与元数据

在 Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入 java 堆中,这样可以加载多少类的元数据就不再由MaxPermSize 控制, 而由系统的实际可用空间来控制。

垃圾回收

在这里插入图片描述

如何确定垃圾

1 引用计数法

在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用,即他们的引用计数都不为 0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。

2. 可达性分析

为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

垃圾回收算法:

1 标记清除算法

最基础的垃圾回收算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。如图
在这里插入图片描述
从图中我们就可以发现,该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。

2 复制算法

为了解决 Mark-Sweep 算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉,如图:在这里插入图片描述
这种算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是可用内存被压缩到了原本的一半。且存活对象增多的话,Copying 算法的效率会大大降低。

3标记整理算法

结合了以上两个算法,为了避免缺陷而提出。标记阶段和 Mark-Sweep 算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。如图
在这里插入图片描述
标记/整理算法唯一的缺点就是效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。 从效率上来说,标记/整理算法要低于复制算法

4分代收集算法

分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老生代Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。

新生代与复制算法

目前大部分 JVM 的 GC 对于新生代都采取 Copying 算法,因为新生代中每次垃圾回收都要回收大部分对象,即要复制的操作比较少,但通常并不是按照 1:1 来划分新生代。一般将新生代划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。

老年代与标记清除算法–标记整理算法

而老年代因为每次只回收少量对象,因而采用 Mark-Compact 算法。
标记清除(回收):1. 首先会从GC root进行遍历,把可达对象(存过的对象)打标记 2. 再从GC root二次遍历,将没有被打上标记的对象清除掉。
针对老年代对象存活率高的特点,提出了一种称之为”标记-整理算法”。标记过程仍与”标记-清除”过程一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。流程图如下:
在这里插入图片描述
发生在老年代的GC称为Full GC,又称为Major GC,其经常会伴随至少一次的Minor GC(并非绝对,在Parallel Scavenge收集器中就有直接进行Full GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。

  1. JAVA 虚拟机提到过的处于方法区的永久代(Permanet Generation),它用来存储 class 类,常量,方法描述等。对永久代的回收主要包括废弃常量和无用的类。
  2. 对象的内存分配主要在新生代的 Eden Space 和 Survivor Space 的 From Space(Survivor 目前存放对象的那一块),少数情况会直接分配到老年代。
  3. 当新生代的 Eden Space 和 From Space 空间不足时就会发生一次 GC,进行 GC 后,Eden Space 和 From Space 区的存活对象会被挪到 To Space,然后将 Eden Space 和 From Space 进行清理。
  4. 如果 To Space 无法足够存储某个对象,则将这个对象存储到老年代。
  5. 在进行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反复循环。
  6. 当对象在 Survivor 区躲过一次 GC 后,其年龄就会+1。默认情况下年龄到达 15 的对象会被移到老生代中。

什么是GC Root

在这里插入图片描述
在这里插入图片描述
在java中哪些可以作为GC Root的对象:
虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
方法区中的类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI(Native方法)引用的对象。

JVM参数类型:

1 标配参数 2 X参数(了解) 3 xx参数

1 标配参数如下:
在这里插入图片描述
在这里插入图片描述
2 x参数
在这里插入图片描述
3xx参数
在这里插入图片描述
第一种Boolean型

在这里插入图片描述
如何查看一个正在运行中的java程序,它的某个jvm参数是否开启?具体值是多少?
jps 相当于是 java ps对应于Linux下的ps指令 :查看当前java下正在运行的程序
在这里插入图片描述
查看13632有没有开启对应的服务
在这里插入图片描述
XX:–说明没有开启。

在这里插入图片描述
那么重新关闭来一次
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第二个KV参数:
在这里插入图片描述
第一个参数是改变初始内存的大小,第二个参数是控制对象有多少次GC就能进老年代
在这里插入图片描述

java查看默认值:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

JVM常用配置参数

Xms,Xmx,Xss,Xmn,XX:MetaspaceSize,XX:+PrintGCDetails,
XX:SurvivorRatio,XX:NewRatio,XX:MaxTenuringThreshold

在这里插入图片描述
-Xmn 用来设置新生代的大小。

java1.7及以前叫永久代,1.8就变为了元空间。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
JVM默认配置的参数:
在这里插入图片描述
配置上面的那一串参数以后
在这里插入图片描述
配置后再次查看
在这里插入图片描述
在这里插入图片描述
默认情况是8:1:1
在这里插入图片描述
修改后,变成了4:1:1
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
最大值为15
在这里插入图片描述

四大引用指的是什么

在这里插入图片描述

强引用

当内存不足,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。
强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。在Java中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收。因此强引用是造成Java内存泄漏的主要原因之一。
对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为null,一般认为就是可以被垃圾收集的了(当然具体回收时机还是要看垃圾收集策略)。
例子:
在这里插入图片描述
o2 与o1指向同一块内存空间,即使o1置空,那么o2也不会丢掉指向被回收掉
在这里插入图片描述

软引用

软引用是一种相对强引用弱化了一些的引用,需要用java.lang.ref.SoftReference类来实现,可以让对象豁免一些垃圾收集。
对于只有软引用的对象来说,
当系统内存充足时它不会被回收,
当系统内存不足时它会被回收。
软引用通常用在对内存敏感的程序中,比如高速缓存就有用到软引用,内存够用的时候就保留,不够用就回收!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

弱引用

弱引用需要用java.lang.ref.WeakReference类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,都会回收该对象占用的内存。
在这里插入图片描述
在这里插入图片描述

软引用和弱引用的适应场景

在这里插入图片描述‘在这里插入图片描述

weekHashMap

在这里插入图片描述
在这里插入图片描述
弱引用
在这里插入图片描述

’

虚引用

虚引用需要java.lang.ref.PhantomRqference类来实现。
顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。
如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。
PhantomReference的get方法总是返回nul,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入finalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。
换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理。Java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

ReferenceQueue 引用队列介绍—》在回收前被放到引用队列保存一下

在这里插入图片描述
弱引用,软引用,虚引用在gc前都会被放到一个引用队列里
在这里插入图片描述

虚引用的案例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
GCRoot和四种引用:
在这里插入图片描述

对OOM的认识

在这里插入图片描述
在这里插入图片描述

1 栈溢出:

在这里插入图片描述
*

2 OutOfMemoryError

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 java.lang.OutOfMemoryError: GC overhead limit exceeded

在这里插入图片描述
GC回收时间过长时会抛出OutOfMNemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到%的堆内存连续多次GC 都只回收了不到2%的极端情况下才会抛出。假如不抛出GC overhead limit 错误会发生什么情况呢?*那就是GC清理的这么点内存很快会再次填满,追使GC再次执行.这样就形戌恶性循环,
*CPU使用率一直是100%,而GC却没有任何成果
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4 java.lang.outOfMemoryError: Direct buffer memory

在这里插入图片描述

5 java.lang.OutOfMemoryError: unable to create new native thread

在这里插入图片描述
在这里插入图片描述
在Linux环境下测试:
在这里插入图片描述

6 java.lang.outOfMemoryError: Metaspace(元空间)

在这里插入图片描述
在这里插入图片描述

垃圾回收器

1 串行垃圾回收器(Serial)

它为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有的用户线程。所以不适合服务器环境

2并行垃圾回收器 (Parallel)

多个垃圾收集线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理首台处理等弱交互场景
在这里插入图片描述

3并发垃圾回收器(CMS)

用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程互联网公司多用它,适用对响应时间有要求的场景
在这里插入图片描述

4 G1垃圾回收器

G1垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收

在这里插入图片描述

如何查看默认的垃圾收集器

在这里插入图片描述

默认的垃圾收集器有哪些

UseSerialGC,
UseParallelGC
UseConcMarkSweepGC,
UseParNewGC,
UseParallelOldGC,
UseG1GC

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

GC之Serial收集器(现在已经不用了)

在这里插入图片描述
在这里插入图片描述

GC之ParNew收集器

在这里插入图片描述

在这里插入图片描述

GC之Parallel收集器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
新生代配置了会自动激活老年代的。
上面那三种是新生代的垃圾回收器,下边这三种是老年代的垃圾回收器

并行 GC(Parallel Old)/(Parallel MSC)

在这里插入图片描述

GC之CMS收集器

在这里插入图片描述
在这里插入图片描述
上图那四步的过程:
在这里插入图片描述

在这里插入图片描述
1只是标记一下GC Roots能直接关联的对象,速度很快,仍然需要暂停所有的工作线程。
2 进行GC Roots跟踪的过程,和用户线程一起工作,不需要暂停工作线程。主要标记过程,标记全部对象

3为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录、仍然需要暂停所有的工作线程。
由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正

4清除GC Root不可达对象,和用户线程一起工作,不需要暂停工作线程。基于标记结果,直接清理对象
由于耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作,
所以总体上来看CMS 收集器的内存回收和用户线程是一起并发地执行。
在这里插入图片描述
在这里插入图片描述
由于并发进行,CMS在收集与应用线程会同时会增加对堆内存的占用,也就是说,CMS必须要在老年代堆内存用尽之前完成垃圾回收,否则CMS回收失败时,将触发担保机制,串行老年代收集器将会以STW的方式进行一次GC,从而造成较大停顿时间

GC之SerialOld收集器 (现在已经不用了)

在这里插入图片描述

G1垃圾回收器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
G1 的特点:
在这里插入图片描述
G1的底层原理:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回收也分四步:
在这里插入图片描述

如何选择合适的垃圾器

在这里插入图片描述
在这里插入图片描述

Tiff、jpg图片怎么样添加地理坐标信息 Tiff、jpg图片怎么样添加地理坐标信息 一般,外业调查只有地图资料,如专题图、或者地形图,如何把这些地图资料的扫描地图带上坐标信息,从而内业实现信息化处理?以上问题,可以解决,但根据不同情况有不同的处理方法。     第一种,上面有经纬度外框,图片是矩形,但是没有地理信息。 通过图框的两个角的坐标确定范围,分别是左上(140°E,30°N);右下(150°W,30°N) 解决方 阅读详情

相关推荐

保姆级教程:用sw_urdf_exporter插件将Solidworks机械臂模型转为ROS可用的URDF

本文提供了一份详细的保姆级教程,指导用户使用sw_urdf_exporter插件将Solidworks机械臂模型转换为ROS可用的URDF文件。从环境准备、插件配置到模型预处理和关键参数设置,再到ROS环境集成测试和性能优化,全面覆盖了机械臂URDF转换的全流程。特别适合机器人工程师和ROS开发者快速实现Solidworks模型到ROS环境的无缝迁移。

weixin_29300931的博客 397

JVM(二)垃圾回收

引用计数法、可达性分析算法;标记-清除算法、复制算法、标记-整理算法、分代收集算法;七种常见垃圾回收器;栈上分配

HK的博客 1117

[AHK] 自动化获取通达信股票代码:从消息钩子到数据提取

本文详细介绍了如何使用AHK(AutoHotkey)通过Windows消息钩子技术自动化获取通达信股票代码,实现高效数据提取和交易自动化。文章涵盖消息机制原理、AHK脚本开发、性能优化及安全注意事项,为股票交易者提供了一套完整的解决方案。

weixin_42614269的博客 616

JVM内存模型

1.jvm内存模型、分区 程序计数器:记录当前线程执行的位置 方法区:用于储存已被虚拟机加载的类信息,常量池(常量,静态变量),即时编译器编译后的代码 堆:存放数组和对象实例 栈:定义基本数据类型的变量,一个对象的引用保存在栈里面 Book b = new Book(); new Book()实例是放到堆里面的 b引用是放到栈里面的 2.堆分区 Java 堆从 GC 的角度细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年......

qq_41482600的博客 228

Windows 24H2下eNSP AR_40启动失败的终极修复指南

本文针对Windows 11 24H2更新后eNSP AR_40路由器启动失败的问题,提供了终极修复方案。核心在于解决系统强制虚拟化安全(VBS/Hyper-V)与老版模拟软件的兼容性冲突。指南详细介绍了安装关键系统更新KB5053656、精细调整Windows虚拟化功能以及后续排错步骤,帮助用户在24H2系统上稳定运行eNSP进行网络实验。

weixin_29233333的博客 507

EtherCAT同步模式实战:如何用TwinCAT配置DC-Synchronous模式(附时序图详解)

本文详细解析了如何在TwinCAT环境中配置EtherCAT的DC-Synchronous同步模式,实现纳秒级同步精度。通过硬件准备、参数配置和高级调优步骤,帮助工程师解决工业自动化中的同步挑战,提升运动控制性能。

gold的博客 1571

JVM 运行时内存(三)

Java 堆从 GC 的角度还可以细分为:Eden 区From Survivor 区和To Survivor 区)和代。

qq_24428851的博客 1466

大模型多智能体协作面试题及参考答案

在多智能体系统里,代理定义自身目标或效用函数的过程与系统架构、应用场景紧密相关。从本质上讲,目标是代理行为的导向,而效用函数则是对目标达成程度的量化评估。代理通常依据自身角色、系统全局需求以及与其他代理的交互关系来确立目标。比如在合作型 MAS 中,代理目标可能需要与全局目标对齐,像多个物流机器人协作完成货物配送时,每个机器人的目标会围绕 “高效完成分配任务”“避免路径冲突” 等展开,其效用函数可能涉及任务完成时间、能耗等指标的加权求和。目标定义的方式存在多种类型。

大模型大数据攻城狮的专栏 1022

JVM 运行时内存

JVM学习目录 1.JVM 概念简介 2.JVM 运行时内存 一、JVM 运行时内存 Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。 二、新生代 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、Servivo...

杨海吉 323

Jetson Thor平台JP7.0版本96712 GMSL相机驱动调试记录

摘要:本文档记录了在Thor Custom Board (JP7.0GA)上配置GMSL摄像头时遇到的视频流问题及调试过程。问题表现为视频设备(/dev/video11)能正常创建,但获取视频时出现"Internal data stream error",而相同配置在AGX Orin JP6.0上运行正常。通过梳理硬件拓扑、v4l2-ctl测试、提升时钟频率及分析内核日志,发现VI引擎未接收到帧数据包。调试步骤包括检查设备树冲突、调整I2C总线配置、修正通道名称,最终通过屏蔽传感器启动时

jzwjzw19900922的博客 1109

飞牛fnNAS个人小账本导入微信账单

本文介绍了将微信支付账单导入ezBookkeeping个人记账系统的详细方法。首先通过微信申请导出账单文件,接收后需进行Excel预处理:删除前导行、添加账户和分类列、整理金额格式等。在ezBookkeeping中需预先设置"微信"分类和账户。导入时需注意列映射关系,包括交易时间、账户名称等关键字段的对应设置。文章还提到处理交易标签、格式转换等细节问题,并建议避免使用"修改余额"功能。该方法同样适用于支付宝账单导入,解决了直接导入可能出现的格式不兼容问题。

dgnankai的专栏 482

JAVA虚拟机(JVM)--叁

JVM 运行时内存 Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。 新生代 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区。 Eden 区 Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当 Ede..

Mr權 485

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【关于JVM,不得不知道的那些事儿】

一、JVM内存区域划分 JVM主要是分成四个区域:堆、栈、程序计数器、方法区 JVM本质上是一个java进程,JVM启动之后就会从操作系统这里申请到一大块内存~ 每个线程,都有自己的栈和程序计数器~ 下面我们对于这四个区域进行详细的描述~ 1.堆:里面放的就是new出来的对象 我们程序中每new一个实例对象,就会放到堆中。 2.方法区:里面放的是类对象 .java =》 .class =》 JVM就会把 .class进行加载,加到内存里=》类对象 类对象里都包含哪些内容: 类的st

weixin_54161577的博客 1489

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

jvm那些事儿

JVM那些事儿 Java内存区域 1.概述 对于Java程序员,在虚拟机自动内存管理机制下,不再需要像C/C++程序员,为每一个new操作去写对应的delete操作,不容易出现内存泄漏和内存溢出问题 2.运行时数据区域 Java虚拟机在执行Java程序的过程中会将它管理的内存分成若干个不同的数据区域 2.1程序计数器 程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。...

追梦的小狼狗 311

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

JVM那点事儿

1、JVM运行时数据区 线程共享数据区:方法区、堆 线程隔离数据区:虚拟机栈、本地方法栈、堆、程序计数器 JVM内存模型之程序计算器 a、程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器 b、线程是一个独立的执行单元,是由CPU控制执行的 c、字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成 d、为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序

放羊的砍柴人 256

关于JVM的那些事儿!

1.基本概念 JVM 是可运行 Java 代码的假想计算机 ,包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收,堆 和一个存储方法域。JVM是运行在操作系统之上的,它与硬件没有直接的交互。 2.运行过程 我们都知道 Java 源文件,通过编译器,能够生产相应的.Class 文件,也就是字节码文件,而字节码文件又 通过 Java 虚拟机中的解释器,编译成特定机器上的机器码 。也就是如下: ① Java 源文件—->编译器—->字节码文件 ② 字节码文件—->J

qq_34433301的博客 212

理解JVM字节码,做点有意的事儿

作者:侯树成来源:Tomcat那些事儿JVM 字节码,做为虚拟机执行的指令,对于平时做 Java 应用开发来说,一直像蒙着一层神秘面纱,朦朦胧胧。但其实理解了字节码指令,对于 Jav...

华章IT官方博客 350

面试官问你关于JVM性能调优那些事儿,你要怎样优雅回答?

对于工作3年左右的Java程序员来说,在面试大厂的过程中,面试官可能不会太关注你做了多少个项目、你的CRUD水平如何。更多的是关注你对某项技术点的理解深度,所以说,工作3年左右的小伙伴一定要把自己的重心放到技术的深度上来。 今天,我们先一起聊聊关于JVM性能调优的话题,本文的主要结构如下所示。 常见面试题 关于JVM,一道常见的面试题就是:Java中创建的对象是存储在JVM中的哪个区域的? 例如,这里,我们简单的列举一行代码,如下所示。 User user = new User();

wdj_yyds的博客 3004

《面试必考》 — JVM那些事儿

俗话说JVM与JUC不分家,前篇已经提到过JUC(传送门—>

m0_68921558的博客 419

JVM那些事儿之执行原理(二)

JVM那些事儿之执行原理(二)案例当一个java程序员把第一个helloworld程序敲出来后,它是怎么在console里打印出“helloworld”的?编写Java程序public class HelloWorld { public static void main(String[] args) { System.out.println(“hello world!”);

小刀 409

关于Java虚拟机JVM的简单了解

JVM主要功能 Java是一种高级编程语言。用高级语言编写的程序不能直接在任何机器上运行。首先,需要将其翻译成特定的机器语言,javac编译器就专门来干这个事儿的,它把Java程序(含有的.java源代码文件)转换成机器代码(称为字节码或.class文件)。 Java虚拟机(JVM)是安装在我们计算机中的虚拟机,JVM自己的机器语言是字节码。这样子Javac编译器就好处理啦,因为它只需要...

weixin_30828379的博客 99

JVM中的对象及引用的那些事儿

JVM中对象的创建流程 对象的内存分配 当虚拟机遇到一条new指令的时候,首先会检查是否被类加载过了。如果没有先必须执行相应的类加载。类加载就是把class文件加载到JVM运行时数据区的过程。 检查加载 首先检查这指令的参数是否能在常量池中定位到一个类的符号引用(符号引用:符号引用以一组符号来描述所引用的目标),并且检查类是否已经被加载、解析和初始化过。 分配内存 接下来虚拟机将为新生对象分配内存。为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。 指针碰...

weixin_47184173的博客 392

JVM那些事儿之内存区域

相信绝大多数java开发者或多或少的都应该知道jvm,但是有多少人又深入去了解过,笔者深感自身能力的不足,去看了些资料,觉得还是有必要整理下自己的学习记录,时常回头看看,多看多实践提升自己的能力,故开始进行jvm相关的知识梳理和记录,一起来学习吧 前言 从我们刚开始学习java时,我们就被告知其“一次编写,到处运行”的特点,随着学习和工作的深入,你也应该了解了构成这种特点的原因,说到这里,有点像中...

Orange's Life 170

JVM专题七:JVM垃圾回收机制

中,我们介绍了JVM内存主要分哪些区域,这些区域分别是干什么的,同时也举了个例子,在运行过程种各个区域数据是怎样流转的。细心的小伙伴可能发现一个问题,在介绍完方法弹栈以后就没有介绍后续流程了。方法执行完以后,堆内存存放的对象实例咋整呢,带着这样的疑问进入今天的内容。

Jeremy程序员 2万+

一文搞懂JVM的可达性分析算法那点破事儿

一文搞懂JVM的可达性分析算法那点破事儿

weixin_62238621的博客 1638

JVM工作原理那些事儿

JVM工作原理和特点 我们运行和调试Java程序的时候,经常会提到一个JVM的概念.JVM是Java程序运行的环境,但是他同时是一个操作系统的一个应用程序也是一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间. 首先来说一下JVM工作原理中的jdk这个东西,不管你是初学者还是高手,是j2ee程序员还是j2se程序员,jdk总是在帮我们做一些事情.我们在了解Java之前

flowingWater 460
上一篇: java多线程之-------阻塞队列-----线程池
下一篇: java ----IO/NIO/AIO
凌晨里的无聊人
博客等级 码龄8年 2320粉丝 206原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨里的无聊人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值