怎样做免费网站推广/网站页面优化方案
Java虚拟机是Java的核心和基础,他是Java编译器和操作系统平台之间处理器,能实现跨平台运行Java程序。本文主要讲解的是虚拟机如何管理对象,即Java对象在JVM虚拟机中被创建到回收的流程
Java对象从创建到回收的生命周期
- 对象创建流程
- 1.类加载检查
- 类加载过程
- 2.分配内存
- JVM运行时内存数据区布局
- 运行时数据区关系
- 3.初始化
- 4.设置对象头
- 5.执行init方法
- 对象回收流程
- 1.标记存活对象
- 2.非存活对象回收
- 垃圾回收策略
- 垃圾回收算法
- 垃圾回收器
- Serial收集器
- Parallel Scavenge收集器
- ParNew收集器
- CMS
对象创建流程
public class Main {public static void main(String[] args) {createObject();}public static void createObject() {Object object = new Object();}
}
当虚拟机碰到new或者克隆一个类的实例对象时【如上new Object()】,它会经历如下过程:
1.类加载检查
当虚拟机遇到一个new指令的时候,首先去判断这个指令的参数是否能在方法区找到类的引用,并且检查这个引用是否已经被加载,解析和初始化过。如果没有,则必须先执行先执行类的加载过程
类加载过程
参考博客:Java类的加载过程
2.分配内存
当类加载完以后,虚拟机将会为新生对象分配内存。对象所需的内存大小在类加载完后便可完全确定,便会将Java堆中一块确定大小的内存从Java堆中划分出来
此时会涉及两个问题
2.1.虚拟机如何分配内存
2.2.在并发情况下,如何保证多个对象的内存不重叠
JVM运行时内存数据区布局
a)堆区
Java堆是用来存储对象本身的以及数组。堆是被所有线程共享的,在JVM中只有一个堆。堆有分代逻辑,堆划分为了年轻代,老年代;年轻代分为了eden区,s0区,s1区,比例默认为老年代:年轻代=2:1,eden:s0:s1=8:1:1;
这里引发两个问题:
1.为什么堆中要分代?
2.为什么年轻代还要分为3个区?为什么区的比例为8:1:1?
会涉及到关于对象回收的机制:
1.堆中分代是为了提高效率,对象是有生命周期,有的对象存活时间长,有的对象存活时间短,存活时间长的放到老年代;存活时间短的放到年轻代。老年代回收频率低点,年轻代回收频率高点
2.分为3个区是为了gc之后方便把存活的对象复制到s1或者s2中,方便内存整理。比如为8:1:1是因为大多数的对象都是朝生夕死的,存活时间比较短,所以jvm默认8:1:1的比例是合适的,让 Eden区尽量大,survivor区足够用即可
b)栈
Java栈中存放一个个栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括:局部变量表,操作栈,动态链接【指向当前方法所属的类的运行时常量池的方法】,方法出口【方法执行完后需返回地址】
c)本地方法栈
本地方法栈与Java栈作用和原理类似,区别在于Java栈是为执行本地方法服务的,而本地方法栈则是执行本地方法服务的
d)方法区
与堆一样,是线程共享的区域。在方法区中存储了类信息,静态变量,常量以及编译器编译后的代码
e)程序计数器
在jvm中,多线程是通过线程轮流切换来获得cpu执行时间的。为了保证每个线程在切换后能够恢复到切换之前程序执行的位置,每个线程都有自己独立的程序计数器
运行时数据区关系
由下图可以看出:堆和方法区是所有线程共用的,本地方法栈,Java栈,程序计数器是线程私有的
看到堆中存放对象,引发两个问题:
1.所有新创建对象都存放到堆中吗?
2.堆中既有老年代又有年轻代,新创建的对象应该放在哪里
我们先整体看一下对象在内存的分配流程,然后再逐一回答上面的问题
根据图流程所示回答第一个不是所有的对象都会存放到堆中,有可能是栈。栈上分配主要是虚拟机根据该对象是否被外部访问。如果不会逃逸出该对象在栈上分配,随着方法的结束出栈而销毁。
对象逃逸分析:分析对象的动态作用域,当一个对象在方法中被定义后,它可能被外部方法引用,例如被作为参数传递到其他地方去
public User createUser(){User user = new User();user.setName("judy");user.setAge(18);return user;
}public void test1(){User user = createUser();
}
像上面的方法,它可能被其他方法调用,无法在栈内分配;而像作用域非常确定,比如:
public void createUser(){User user = new User();user.setName("judy");user.setAge(18);
}
那这种作用域非常确定,不会被其他方法调用,就可以在栈内分配。
因为栈内存比较小,为了防止栈内没有一大块连续空间导致对象内存不够分配,虚拟机会采用标量替换方法去解决这个问题
标量替换:当对象确定在栈内分配时候,并且开启了标量替换,它不会直接创建对象,因为创建对象需要设置对象头也会占用空间,而是将该Java对象成员变量进行分解,分为若干个被这个方法使用的局部成员变量,然后为分解后的变量分配空间。jdk7以后默认开启。标量一般是指Java中的基本数据类型
解决完第一个问题:对象否则都存在于堆中?我们再来看第二个问题:堆中既有老年代又有年轻代,新创建的对象应该放在哪里?
第二个问题的答案是:一个新创建的对象,如果非常大,超过虚拟机设置的值,就会直接放到老年代;但是如果没有超过限定值,先放到Eden中。至于S0,S1区,对象在通过minorGC以后才会存放到这两个区域中,后续讲解到对象的垃圾回收时,还会重点解决一下。
3.初始化
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值【不包括对象头】。这一步保证对象的实例字段在Java代码中可以不赋初始值就直接使用,程序就能访问到这些字段的数据类型所对应的零值
4.设置对象头
对对象的实例属性值设置为零值后,需要对对象进行必要的设置,例如这个对象属于哪个类的实例,如果才能找到类的元数据信息,对象的哈希码,对象gc分代信息。这些信息在对象的对象头中。
对象分为三部分信息:对象头,实例数据,对象填充
4.1对象头:分为三部分信息
4.1.1第一部分存储对象自身运行时的数据
4.1.2第二部分存储类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针确定这个对象属于哪个类的实
4.1.3第三部分是数组长度,若为数组则有数,若没有则为空
4.2实例数据:对象的实例属性
4.3对象填充:当对象头+实例数据的字节数不是8字节的整数时,字节填充使其为8字节的整数倍,加快内存寻址
5.执行init方法
为对象赋值和执行构造方法
对象回收流程
1.标记存活对象
对象回收之前,先判断对象是否活着,判断对象是否活着两种方式
1.引用计数法
给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;
当引用失效,计数器就减1;任何时候计数器为0的对象就是不可能再被使用的。这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。
2.可达性分析算法
将"GC Roots"对象作为起点,从这些起点开始向下搜索引用的对象,找到的对象是非垃圾的对象,其余标记为垃圾对象。
GC Roots根节点:线程栈的本地变量,静态变量,本地方法栈中的变量
其中引用关系可以分为:强引用,软引用,弱引用,虚引用
强引用:普通的变量引用
public static User user=new User();
软引用:被SoftReference对象包裹着,正常情况不会被回收,但是gc做完后发现释放不出空间存放新的对象,则会将这些软引用对象回收掉。用来实现内存敏感的高速缓存
public static SoftReference<User> user=new SoftReference<User>(new User());
弱引用:将对象用WeakReference软引用类型的对象包裹着,弱引用跟没有引用差不多,GC会直接回收掉。
虚引用:最弱的引用,几乎不用
引发一个问题,是否没有可达性分析分析到的对象就会被回收?
答案是不会,一个对象被回收要经历两次标记的过程
1.第一次标记进行筛选
筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize方法,对象将直接被回收。
2.第二次标记
第二次标记如果这个对象覆盖了finalize方法,finalize方法是对象脱逃死亡命运的最后一次机会,如果对象要在finalize()中成功拯救
自己,只要重新与引用链上的任何的一个对象建立关联即可,譬如把自己赋值给某个类变量或对象的成员变量,
那在第二次标记时它将移除出“即将回收”的集合。
如果对象这时候还没逃脱,那基本上它就真的被回收了。
注意:
一个对象的finalize()方法只会被执行一次,
也就是说通过调用finalize方法自我救命的机会就一次。
2.非存活对象回收
被标记的对象是如何在内存中被回收,首先堆在内存是分代的,两者根据对象生命周期的不同,存放着不同类型的对象。那意味着也需要采取不同的回收策略【年轻代回收和老年代回收】,回收策略也有着相应的回收算法,根据不同垃圾回收算法JVM也提供了一系列垃圾回收器
垃圾回收策略
Minor GC/Yong GC:指发生新生代的垃圾收集动作,Minor GC会非常的频繁,回收速度一般比较快;
Major GC/Full GC:一般会回收老年代,年轻代,方法区的垃圾,Major GC的速度一般会比Minor GC慢
垃圾回收算法
-
标记复制
将内存分为大小相同的两块,每次使用其中的一块。当一块用完后,将存活的对象复制到另一块去,然后把使用的空间一次清理掉。
-
标记清除
算法分为标记和清除阶段:标记存活的对象,统一回收所有未被标记的对象;也可以标记需要回收的对象,在标记完成后统一回收被标记的对象。它是最基础的手机算法,比较简单,但是会带来1个问题:清除后产生大量不连续的碎片
-
标记整理
根据老年代特有的标记算法,标记过程和标记-清除算法一样,但后续步骤不是直接对可回收的对象回收,而是让所有存活的对象向一端移动,然后直接清理掉边界以外的内存。
垃圾回收器
垃圾回收算法是内存分配的方法论,那么垃圾回收器是内存分配的具体实现
Serial收集器
Serial(串行)收集器是最基本、历史最悠久的垃圾收集器了。
大家看名字就知道这个收集器是一个单线程收集器了。它的“单线程”的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程(“StopTheWorld”),直到它收集结束。新生代采用复制算法,老年代采用标记-整理算法。
Serial Old收集器是Serial收集器的老年代版本,它同样是一个单线程收集器。可以和CMS收集器搭配使用
配置参数如下:
-XX:+UseSerialGC
-XX:+UseSerialOldGC
Parallel Scavenge收集器
Parallel收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,
其余行为(控制参数、收集算法、回收策略等等)和Serial收集器类似。
默认的收集线程数跟cpu核数相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改。Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)
CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)
新生代采用复制算法,老年代采用标记-整理算法。
Parallel Old收集器是Parallel Scavenge收集器的老年代版本。
使用多线程和“标记-整理”算法。在注重吞吐量以及CPU资源的场合,都可以优先考虑
ParallelScavenge收集器和Parallel Old收集器(JDK8默认的新生代和老年代收集器)。
参数配置:
-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代)
ParNew收集器
ParNew收集器其实跟Parallel收集器很类似,区别主要在于它可以和CMS收集器配合使用。
新生代采用复制算法,老年代采用标记-整理算法。
参数配置:
-XX:+UseParNewGC
CMS
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。
它非常符合在注重用户体验的应用上使用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。从名字中的MarkSweep这两个词可以看出,CMS收集器是一种“标记-清除”算法实现的,它的运作过程相比于前面
几种垃圾收集器来说更加复杂一些。
整个过程分为四个步骤:
初始标记:
暂停所有的其他线程(STW),并记录下gcroots直接能引用的对象,速度很快。
并发标记:
并发标记阶段就是从GCRoots的直接关联对象开始遍历整个对象图的过程,
这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。
因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。
重新标记:
重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。主要用到三色标记里的增量更新算法做重新标记。
并发清理:开启用户线程,同时GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理
并发重置:重置本次GC过程中的标记数据。
参数配置:
-XX:+UseConcMarkSweepGC(old)
Java虚拟机对对象的管理讲解的这里,有问题可以留言喔
相关文章:

一文了解Hotspot虚拟机下JAVA对象从创建到回收的生命周期
Java虚拟机是Java的核心和基础,他是Java编译器和操作系统平台之间处理器,能实现跨平台运行Java程序。本文主要讲解的是虚拟机如何管理对象,即Java对象在JVM虚拟机中被创建到回收的流程 Java对象从创建到回收的生命周期对象创建流程1.类加载检…...

【Java基础】Java对象创建的几种方式
先上关键内容,所用到的代码请参考文末示例代码。一、使用new关键字创建对象这是一种最常用的创建对象的方式。Student student1 new Student();二、使用Class的newInstance()方法创建对象需要有一个无参构造方法,这个newInstance()方法调用无参的构造函…...

社保缴费满15年就可以不缴了?6个很多人最关心的问题权威解答来了
一、社保缴费满15年就可以不缴了? 上海市政府新闻办公室2022年在微信号发文表示,社会保险是由国家通过立法强制建立的社会保障制度,用人单位和劳动者都必须依法参加社会保险。即使职工与用人单位商议签订了不参加社保的所谓“协议”…...

关于HDFS
目录 一、HDFS概述 二、HDFS架构与工作机制 三、HDFS的Shell操作 四、Hdfs的API操作 一、HDFS概述 HDFS:Hadoop Distributed File System;一种分布式文件管理系统,通过目录树定位文件。使用场景:一次写入,多次读出…...

C++入门:类 对象
C 在 C 语言的基础上增加了面向对象编程,C 支持面向对象程序设计。类是 C 的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成…...

Python生日系统
#免费源码见文末公众号# 录入生日 def write():keyvar1.get()valuevar2.get()with open(d:\\生日系统.pickle,rb) as file:dictspickle.load(file)dicts[key]valuewith open(d:\\生日系统.pickle,wb) as file:pickle.dump(dicts,file)file.close() 查询生日 def read():namev…...

< CSDN周赛解析:第 28 期 >
CSDN周赛解析:第 27 期👉 第一题: 小Q的鲜榨柠檬汁> 题目解析> 解决方案👉 第二题: 三而竭> 解析> 解决方案> 拓展知识👉 第三题: 隧道逃生> 解析> 解决方案👉…...

【题外话】如何拯救小米11Pro这款工业垃圾
1 背景媳妇用小米11Pro手机,某日不慎摔落,幸好屏幕未碎,然而WiFi却怎样都无法打开,初以为是系统死机,几天依旧故障无法使用。现在的手机没有WiFi功能,就无法刷抖音、看视频,就是鸡肋了。后抽空去…...

Python中有哪些常用操作?这20个你都会吗
Python 是一个解释型语言,可读性与易用性让它越来越热门。 正如 Python 之禅中所述: 优美胜于丑陋,明了胜于晦涩。 在你的日常编码中,以下技巧可以给你带来意想不到的收获。 1、字符串反转 下面的代码片段,使用 P…...

【LeetCode】剑指 Offer(4)
目录 写在前面: 题目:剑指 Offer 10- I. 斐波那契数列 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 题目:剑指 Offer 10- II. …...

庄懂的TA笔记(十二)<>
庄懂的TA笔记(十二)<>一、作业展示,答疑:1、作业:2、答疑:二、作业示范,分析:1、文档分析:2、资源分析:3、资源优化:4、光…...

学分绩点(2023寒假每日一题 5)
北京大学对本科生的成绩施行平均学分绩点制(GPA)。 既将学生的实际考分根据不同的学科的不同学分按一定的公式进行计算。 公式如下: 实际成绩 绩点 90——100 4.0 85——89 3.7 82——84 3.3 78——81 3.0 75…...

Framework学习之旅:Zygote进程
概述 在Android系统中,DVM(Dalvik 虚拟机和ART、应用程序进程以及运行系统的关键服务SystemServer进程都是由Zygote进程来创建的。通过fork(复制进程)的形式来创建应用程进程和SystemServer进程,由于Zygote进程在启动时会创建DVM…...

HTTP基础知识
关键字:一问一答用于和服务器交互什么是HTTPHTTP是个应用层协议,是HTTP客户端和HTTP服务器之间的交互数据格式。所以这里有个实例:在浏览网页的时候,浏览器会向服务器发送一个HTTP请求,告诉服务器我想访问什么..然后服…...

Delphi 10.4.2使用传统代码提示方案(auto complete)(转)
Delphi 10.4重点是实现了LSP,但现在最新的10.4.2还是不成熟,无法满足日常需要,不过没关系,可以设置为原有的方案,如下图:具体操作:Tools->Options->Editor->language->Code Insight…...

存储类别、链接与内存管理(三)
1、malloc函数详解 (1)函数声明 #include <stdlib.h> void* malloc(size_t size);malloc可以申请一定数量的空闲内存,这样的内存是匿名的,也就是malloc不会为其赋名,但是确实返回动态分配内存块的首元素地址&a…...

Java:Linux(CentOS)安装、配置及相关命令
目录一、VMware安装二、CentOS安装1、安装过程2、加载ISO2.1 桌面的设置三、VI/VIM编辑器1、一般模式2、编辑模式3、命令模式4、模式间转换四、网络配置和系统管理操作1、配置子网IP和网关2、配置虚拟机ip地址2.1 ifconfig 查询ip地址2.2 修改IP地址3、配置主机名3.1 hostname …...

Linux 操作系统原理 — 多任务优先级调度策略
目录 文章目录 目录多任务优先级调度策略User Process 调度策略配置调整 User Process 的优先级调整非实时进程的优先级调整实时进程优先级调整 User Process 的调度算法多任务优先级调度策略 在 Linux Kernel 中,Kernel Thread 作为唯一的调度实体,Kernel Scheduler(调度程…...

链表学习之找到两个链表相交的第一个节点
链表解题技巧 额外的数据结构(哈希表);快慢指针;虚拟头节点; 找到两个链表相交的第一个节点 给定两个链表,这两个链表可能有环,可能无环。判断这两个链表是否相交,相交则返回第一…...

【Kubernetes】【十一】Pod详解 Pod的生命周期
Pod生命周期 我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期,它主要包含下面的过程: pod创建过程 运行初始化容器(init container)过程 运行主容器(main container) 容器启动后钩子&#…...

Connext DDS录制服务 Recording Service(1)
1 序言 1.1 简介 RTI记录服务包括以下工具: •记录服务,一种RTI Connext DDS应用程序,用于记录主题和发现数据。记录服务记录数据更新以及时间戳,因此您可以查看或回放系统中随时间发生的数据更新。默认情况下,记录的数据存储在SQLite文件中。录制服务还具有一个API,用于…...

vTESTstudio - VT System CAPL Functions - VT2004(续2)
不要沮丧,不必惊慌,做努力爬的蜗牛或坚持飞的笨鸟,我们试着长大,一路跌跌撞撞,哪怕遍体鳞伤。vtsSetPWMVoltageLow - 设置PWM输出上的低电压功能:指定数字输出信号(尤其是PWM信号)输…...

每天一个linux命令---awk
awk命令 1. 简介 awk是一种处理文本文件的语言,是一个强大的文本分析工具,grep、sed、awk并称为shell中文本处理的三剑客。 AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。 之所以叫 AWK 是因为其取了三位创始人 Alfred Aho&am…...

Open3D 点云旋转之轴角式(Python版本)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 三维空间中表示旋转的方法有很多种,轴角式是其中非常经典的一种表示方式。虽然欧拉角表示旋转的方法很是常用,但欧拉角存在着万向锁这个问题,因此轴角式旋转在旋转使用中更为合适。其原理也很是明了,如下所述:…...

Error: Timeout trying to fetch resolutions from npm
文章目录问题描述【最终解决】我搜索到的解决方案npmjs 该依赖各版本列表及对应的被下载次数github issue 说降级到0.0.3就可以正常运行了SOF 也说降级别到0.0.3问题描述 在项目里用到了 "preinstall": "npx npm-force-resolutions"配置,在一台…...

Python基础3
目录 1. 函数多返回值 2. 函数多种传参方式 3. 匿名函数 3.1 函数作为参数传递 3.2 lambda匿名函数 4. 文件的读取操作 4.1 open()打开函数 4.2 读操作方法 4.3 文件的写入 4.4 文件的追加 5. 异常的捕获方法 5.1 捕获常规异常 5.2 捕获指定…...

高可用集群(HAC)
1、高可用集群keepalive说明 高可用定义: 目的:尽可能的提高服务的可用性 99%、99.9%、99.99%、99.999% 实现原理:心跳检测服务: 有状态: MySQL 无状态: apacheLVS Keepalive原理 案例环境专为 LVS和…...

python基于django微信小程序的适老化老人健康预警小程序
随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代, 适老化老人健康预警微信小程序就是信息时代变革中的产物之一。 任何系统都要遵…...

基于微信小程序图书馆管理系统
开发工具:IDEA、微信小程序服务器:Tomcat9.0, jdk1.8项目构建:maven数据库:mysql5.7前端技术:vue、uniapp服务端技术:springbootmybatis-plus本系统分微信小程序和管理后台两部分,项…...

将镭神C32激光雷达的PointXYZ数据转化为PointXYZIR格式 - 附代码
之前遇到过“镭神32线激光雷达ROS下运行fromRosMsg()报错 Failed to find match for field “intensity“ 问题”, 当时确定了是镭神C32雷达缺少相应字段,并记录博客【学习记录】镭神32线激光雷达ROS下运行fromRosMsg()报错 Failed to find match for fi…...