简单了解JVM

一.JVM简介

jvm及Java virtual machineJava虚拟机,它是一个虚构出来的计算机,一种规范。其实抛开这么专业的句子不说,就知道 JVM 其实就类似于一台小电脑运行在 windows 或者 linux 这些操作系统环境下即可。它直接和操作系统进行交互,与硬件不直接交互,而操作系统可以帮我们完成和硬件进行交互的工作。

二.JVM运行时数据区

jvm就相当于是一个运行起来的java进程,每运行起来一个进程,jvm就要向内存申请一大块空间,将它划分成不同区域,每个区域有不同作用。jvm运行时数据区也叫做内存布局

1.方法区/元数据区

存放的是类对象(.class文件加载到内存中就是类对象了)

运行时常量池也在方法区,存放字面量与符号引用。

字面量:字符串,final常量,基本数据类型的值

符号引用:类和结构(struct)的完全限定名,字段的名称和描述符,方法的名称和描述符

2.堆

存放代码中new出来的对象。堆占的空间最大

3.栈/虚拟机栈(线程私有)

存放代码执行过程中方法之间的调用关系。其中的每个元素叫做栈帧,每个栈帧代表了一个方法的调用:栈帧里面包含了方法入口,方法返回的位置,方法的形参,返回值,局部变量……

4.程序计数器(线程私有)

它占的空间最小。主要存放“地址”,表示下一条要执行的指令在内存的哪里(也就是在方法区的哪里。在方法区里,每个方法里面的指令都是以二进制形式存储的)

class A{public void a(){}public void b(){}
}

如上a和b方法会被编译成二进制指令,放到.class文件中,当执行类加载时,就可以把.class文件中的内容加载到内存中,此时,方法的指令就进入到类对象中了。

刚开始调用方法时,程序计数器记录的是方法的入口地址。

5.本地方法栈(线程私有)

存放的是由native修饰的方法的调用关系

总结

总结一下:栈以及程序计数器是每个线程都有一份(比如:一个jvm进程中由10个线程,那么就有10个栈和程序计数器),但公用一份堆和方法区

示例

class A{public int n=10;public static int b=100;
}
public class Test {public static void main(String[] args) {A a=new A();}
}

如上,n,b,a,都分别存放在jvm内存的哪里?

a是局部变量,所以a放在栈上。

n是成员变量,它的产生是依赖对象的,也就是说,只有有lA对象才会有n。恰好在main方法中new了一个A对象,这个对象是存放在堆上的,n是跟随对象的,所以n在堆上

b是一个静态成员变量,b只有一份,跟随类对象,所以b在方法区/元数据区

三.JVM类加载

1.类加载过程

加载:

找到.classwen文件,打开文件,读取文件内容。往往代码中会给定某个类的全限定类名(例如java.lang.String),jvm根据类名,在一些指定目录范围内寻找

验证:

.class文件是二进制(每个字节都有特定含义),这个阶段的目的就是确保.class文件的字节流中包含的信息符合《Java虚拟机规范》全部约束要求,保证这些信息被当作代码运行后不会危害到虚拟机自身安全

在java官方文档上就有.class文件的书写规则

准备:

给类对象及其上面的变量分配内存空间,只是分配,还未初始化,此时空间上的内存的数值全为0(此时若尝试打印static成员,就是全0)

解析:

针对类对象中包含的字符串常量进行处理,进行初始化(java代码中用到的字符串常量,在编译后也会进入到.class文件中)。

注意:对于final String s=“text”;这个test会进入到.class文件中,与此同时,.class文件的二进制指令中也会有一个s引用被创建出。按理说,引用变量中存放的是对象的地址,但是.class文件现在只是一个文件,不涉及到地址,所以无法向s中存放text的地址,所以暂时,s中存放的是text在文件中的偏移量,称为文件的偏移量(例如:假设test开头距文件开头为100个字节,那么s中就存放100)等加载到内存中后,再把s的值替换为真正的内存地址)

这个过程也叫做把符号引用替换为直接引用。

初始化:

针对类对象进行初始化:

把类对象需要的各个属性设置好

初始化static成员

执行静态代码块

加载父类

2.双亲委派模型

这个模型用于类加载的第一个阶段:加载过程中寻找.class文件

类加载器:

这是jvm中的一个模块,jvm一共内置了三个类加载器

1.BootStrapClassLoader 爷爷

2.ExtensionClassLoader父亲

3.ApplicationClassLoader儿子

这三个类从上到下构成了父子关系。这个父子关系不是由继承构成的,而是这几个类里面有一个parent属性,指向了一个”父“类加载器(其实说是双亲,实际不是一父一母,而是只有父亲)

基于双亲委派模型的加载过程

1.给定一个类的全限定名

2.从ApplicationClassLoader作为入口,开始查找逻辑

3.ApplicationClassLoader不会立即扫描自己负责的目录(它负责搜索项目当前目录和第三方库对应的目录),而是把查找任务先交给自己的父亲ExtensionClassLoader

4.ExtensionClassLoader也不会立即扫描自己负责的目录(他负责搜索jdk中一些扩展的库对应的目录),而是把查找任务交给自己父亲BootStrapClassLoader

5.BootStrapClassLoader也不想立即搜索自己负责的目录(他负责的是标准库中的目录)。但发现自己没有父亲,因此只能亲自扫描标准库中的目录。但若不是标准库中的类,任务就会被教给孩子执行

6.BootStrapClassLoader没有搜索到,所以就交给了儿子ExtensionClassLoader,扫描扩展库中的目录。

7.没找到就交给孩子ApplicationClassLoader,扫描当前项目和第三方库中的目录。

8.若还是没有找到,就会抛出ClassNotFoundException

目的:

主要是为了确保标准库中的类被加载的优先级最高,其次是扩展库,最后是自己写的类和第三方库。

双亲委派模型不是必须遵守的,它是可以被打破的(在自定义类加载器时可以不遵循)。就比如Tomcat中加载webapp,其中的类只能在webapp中寻找

四.垃圾回收——GC

Java中的垃圾回收机制,主要就是让jvm自己判断某个内存是否不再使用,若确定不用了,jvm就会自动把内存回收。

1.GC回收的目标

它回收的是内存中new出来的对象。那其他的呢?

而对于栈中的局部变量,它是跟随栈帧的生命周期,方法接收,局部变量的空间就自动释放了

而对于静态变量,它的生命周期就是整个程序,始终存在,无需释放。

2.GC大致分为两步

寻找垃圾:

在GC圈子中,寻找垃圾主要有两种主流方案(Java使用的是第二种)

引用计数

new出来的对象,会单独在它的旁边安排一块空间用来保存一个引用计数(计数器),这个计数器描述了这个对象有几个引用指向它。当没有引用指向时,该数就会是0,就可以被视为垃圾。

引用计数的缺点:

1.比较浪费内存空间

    一个计数器,咋说也得2个字节的空间,假设对象本身很小,那么计数器占据的空间比例就很大。

2.引用计数机制存在循环引用问题

class A{public A t;
}
public class Test {public static void main(String[] args) {A a=new A();A b=new A();a.t=b;b.t=a;}
}

上述代码,a、b是局部变量,存放在栈中,堆上的第一个A对象中的t引用存放的是堆上的第二个A对象的地址,堆上的第二个A对象中的t引用存放的是堆上的第一个A对象的地址。所以此时,第一个A对象的引用计数为2(一个是栈上的a,另一个是堆上的第二个A对象的t变量),第二个A对象的引用计数也是2,当代码执行到a=null  b=null后,a、b在栈上的内存被释放了,所以a、b变量消失了,所以第一个A对象的引用计数减一,变成了1(这个1就是堆上的第二个A对象的t变量),同理堆上的第二个A对象的引用计数也变成1了。

到此为止,jvm认为两个对象都有引用指向,所以不是垃圾,所以就不回收

但此时,new出来的两个对象已经无法被其他代码访问到了,但是却没有被回收)

可达性分析

本质:用时间换取空间

有一个/组线程,周期性的扫描代码中的所有对象。就是从一些特定的对象触发,把所有能访问到的对象,都标记成可达,反之未标记的就是垃圾

可达性分析的出发点有很多:不仅仅是局部变量,还有常量池中引用的对象,方法区中的静态引用类型引用的变量……这些出发点就被称为GCRoots

可达性分析是周期性进行的,当前某个对象是否是垃圾,会随代码进行发生改变

回收垃圾:

如何回收垃圾?主要有下面三种做法

标记清除(简单粗暴)

就是把被标记到的对象直接释放掉。

这样非常不靠谱,会产生很多内存碎片。

随着时间推移,内存碎片的情况会愈演愈烈

复制算法

通过copy的方式,把有效对象集中到一起,再同意释放剩余空间

将内存分成大小相等的两份,每次只用其中的一份,当需要进行垃圾回收时,就会先将不需要回收的对象复制到内存中的另一半(是连续复制,不留空位),然后统一释放那一半。

复制算法的缺点:

1.内存浪费一半,内存利用率不高

2.当有效对象很多时,拷贝操作的开销很大。

标记整理

既能解决内存碎片问题,又能解决内存利用率不高的问题

1234567

如上,假如1,4,6是被标记的要被清除的垃圾,标记整理就相当于是顺序表删除元素时的搬运操作:将2搬到1位置,将3般到2位置,将5搬到3位置,将7搬到4位置,最后释放5、6、7位置的元素

标记整理未解决的问题就是搬运操作(copy)的开销很大

jvm的垃圾回收机制-分代算法

jvm找到垃圾后是使用那种方法进行垃圾的回收呢?它采用的是上述三种思路的结合体

分代算法就是通过区域划分,实现不同区域和不同垃圾的回收策略,从而实现更好的垃圾回收。。

首先将一整个内存分为两大部分(不用平均分配),左边统称为新生代,右边就是老年代。在新生代,又划分为伊甸区和幸存区,其中幸存区被均分成两部分。

刚new的对象被放到伊甸区。从对象诞生到第一轮可达性分析扫描,虽然时间不长,但是凭经验来看,该时间内大部分对象都会变成垃圾,剩余不是垃圾的,就被放到幸存区,这个放就可以说是复制算法。由于经验规律(短时间内大部分对象都会变成垃圾的经验),真正需要复制到对象不多,很适合复制算法。

在幸存区的对象,都是活过了第一轮GC的对象。GC的扫描线程也会扫描幸存区,并将活过GC的对象复制到幸存区的另一半,释放上一半。反复像上面这样在幸存区进行多轮GC,使用的也是复制算法

当对象已经在幸存区活过了很多轮GC后,jvm就会认为它短时间内释放不掉了,就会把它放到老年代

老年代的对象被GC扫描的频率很低,从而减少了GC开销

总结:

新生代主要使用复制算法,老年代主要是标记整理。

而标记清除太不靠谱了,所以不采用

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【VS2019】x64 Native Tools Command Prompt for Vs 2019使用conda命令进入环境

【VS2019】x64 Native Tools Command Prompt for Vs 2019使用conda命令进入环境 安装完VS2019后,打开终端x64 Native Tools Command Prompt for Vs 2019,直接运行conda会出现‘conda’ 不是内部或外部命令,也不是可运行的程序 原因分析:这是因为没有设置anaconda的环境变…

SpringBoot学习笔记四

SpringBoot学习笔记四-监听机制 1. SpringBoot监听器1.1 无需配置1.1.1 CommandLineRunner使用1.1.2 ApplicationRunner的使用1.1.3 CommandLineRunner与ApplicationRunner的区别 1.2 需要创建META-INF文件,并在其中创建spring.factories,配置相关的信息…

apline安装redisjson

安装前的说明 由于redis现在下载redisjson很繁琐,还可能需要科学上网,只能自己编译了 系统是apline, 为什么是这个系统?原因是docker安装redis是用了这个系统 下载地址,按照实际情况选择,如果不行就老老实实自己编译吧…

【漏洞复现】用友畅捷通CRM get_usedspace存在SQL注入漏洞

0x01 阅读须知 “如棠安全的技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供…

2024年最佳网页设计师AI工具

人工智能(AI)正在改变设计师相当快速的工作方式,为更智能地工作提供新的效率。 人工智能不再只是一个流行词;它改变了游戏规则。但人工智能能为网页设计师做什么呢?新网页设计师AI工具工具可以为从内容创建到图像细化…

Thingsboard PE智慧运维仪表板实例(一)【智慧排口截污实例】

1、仪表板总览 以该实际落地项目为案例,跟着我一起搭建智慧运维大屏!社区版和专业版都通用。本文是致力于快速搭建,所以不会详细去讲Thingsboard的知识点,只讲如何配置和使用部件。 搭建仪表板的整体效果如下: 点击左侧设备列表可以查看设备详细页面: 2、设备 我的设备都…

2024年第十七届 认证杯 网络挑战赛 (C题)| 云中的海盐 | 辐射传输方程 Stefan-Boltzmann分析 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。 让我们来看看认证杯 网络挑战赛 (C题)&#xff01…

P1090 [NOIP2004 提高组] 合并果子

原题链接:[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 优先队列。 当堆数大于1时,每次将最小的两个(最小堆的堆顶)取出&#xff…

2017NOIP普及组真题 4. 跳房子

线上OJ: 一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid1417\ 核心思想 首先、本题中提到 “ 至少 要花多少金币改造机器人,能获得 至少 k分 ”。看到这样的话语,基本可以考虑要使用 二分答案。 那么,本题中…

2024.4.11

1.思维导图 2.指针形式验证大小端存储 #include<myhead.h>int main(int argc, const char *argv[]) {int num 0x12345678;char* ptr (char *)&num;if(*ptr 0x12){printf("big endian\n");}else if(*ptr 0x78){printf("little endian\n");}r…

Struts2的入门:新建项目——》导入jar包——》jsp,action,struts.xml,web.xml——》在项目运行

文章目录 配置环境tomcat 新建项目导入jar包新建jsp界面新建action类新建struts.xml,用来配置action文件配置Struts2的核心过滤器&#xff1a;web.xml 启动测试给一个返回界面在struts.xml中配置以实现页面的跳转&#xff1a;result再写个success.jsp最后在项目运行 配置环境 …

C++ //练习 11.22 给定一个map<string, vector<int>>,对此容器的插入一个元素的insert版本,写出其参数类型和返回类型。

C Primer&#xff08;第5版&#xff09; 练习 11.22 练习 11.22 给定一个map<string, vector<int>>&#xff0c;对此容器的插入一个元素的insert版本&#xff0c;写出其参数类型和返回类型。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具…

Python 全栈体系【四阶】(二十七)

第五章 深度学习 三、OpenCV 5. 图像梯度处理 5.1 模糊处理 # 图像模糊处理示例 import cv2 import numpy as np## 中值滤波 im cv2.imread("../data/lena.jpg", 0) cv2.imshow("orig", im)# 调用medianBlur中值模糊 # 第二个参数为滤波模板的尺寸大小…

探索基于WebRTC的有感录屏技术开发流程

title: 探索基于WebRTC的有感录屏技术开发流程 date: 2024/4/7 18:21:56 updated: 2024/4/7 18:21:56 tags: WebRTC录屏技术屏幕捕获有感录屏MediaStream实时传输音频录制 第一章&#xff1a;技术原理 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一种开放源…

vue源码解析——v-if和v-for哪个优先级高,如何避免两者同时使用

首先&#xff0c;官方不推荐v-if和v-for在同一个元素上使用。其次&#xff0c;如果两者同时使用&#xff0c;v-if和v-for的优先级怎么确定&#xff1f;在vue2和vue3中这两者的优先级顺序不一样。vue2是v-for优先&#xff0c;条件不存在时也会渲染多个注释节点。在vue3中进行了改…

互联网大厂ssp面经(操作系统:part1)

1. 什么是进程和线程&#xff1f;它们之间有什么区别&#xff1f; a. 进程是操作系统中运行的一个程序实例。它拥有独立的地址空间和资源&#xff0c;可以独立执行。 b. 线程是进程内的一个执行单元&#xff0c;一个进程可以包含多个线程。 c. 线程共享进程的资源&#xff0c;…

HarmonyOS开发实例:【数字管家app】

一&#xff0e;概述 本应用是基于RK3399开发板&#xff0c;使用OpenHarmony3.1-Release开发的应用。通过OpenHarmony的分布式技术&#xff0c;使多人能够一起画画。 1.应用运行效果图&#xff1a; 2.分布式画板使用示意图 如上图所示&#xff0c;用户1、用户2在各自本地端进行…

【Entity Framework】如何使用EF中的生成值

【Entity Framework】如何使用EF中的生成值 文章目录 【Entity Framework】如何使用EF中的生成值一、概述二、默认值三、计算列四、设置主键五、显示配置值生成六、设置日期/时间值生成6.1 创建时间戳6.2 更新时间戳 七、替代值生成八、无值生成九、总结 一、概述 数据库列的值…

【网站项目】校园订餐小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

软考121-上午题-【软件工程】-敏捷方法

一、敏捷方法 敏捷开发的总体目标是通过“尽可能早地、持续地对有价值的软件的交付”使客户满意。通过在软件开发过程中加入灵活性&#xff0c;敏捷方法使用户能够在开发周期的后期增加或改变需求。 敏捷过程的典型方法有很多&#xff0c;每一种方法基于一套原则&#xff0c;这…