jvm-狂神课程

news2024/9/22 1:29:36

一、JVM

JVM就是Java虚拟机,Java虚拟机就是JVM

1. JVM位置

6d6c0eefe96d780c0e37be2427ea91a0

  • 1、Java程序(跑的环境是在jvm(虚拟机)跑的,也可以说是在jre上跑的)java运行是需要在特定的环境的也就是这个jre这种。

  • 2、jvm(也就是jrejre包括了jvm):jvm是用c写的

  • 3、操作系统(也是个软件

  • 4、硬件体系(Intel,sapc)

2. JVM体系结构

2.1. jvm结构图

image

image

  • 1、java编译 - 命令javac

  • 2、编译生成Class File

  • 3、类装载器(类加载器Class Loader

  • 4、运行时数据区:(类加载完成后进入这个运行时数据区:Runtime Data Are)运行时异常是不可捕获的。这是在类加载器后的产物!运行时数据区里面就有(方法区(Method Area),java栈(stack),本地方法栈(Native Method Stack),堆(heap) ,程序计数器(pc寄存器))

    • 本地方法栈: 本地方法栈也是线程私有的数据区,本地方法栈存储的区域主要是 Java 中使用 native 关键字修饰的方法所存储的区域。
    • 程序计数器:程序计数器也是线程私有的数据区,这部分区域用于存储线程的指令地址,用于判断线程的分支、循环、跳转、异常、线程切换和恢复等功能,这些都通过程序计数器来完成。
    • 方法区:方法区是各个线程共享的内存区域,它用于存储虚拟机加载的 类信息、常量、静态变量、即时编译器编译后的代码等数据。
    • :堆是线程共享的数据区,堆是 JVM 中最大的一块存储区域,所有的对象实例都会分配在堆上。JDK 1.7后,字符串常量池从永久代中剥离出来,存放在堆中。
    • 运行时常量池:运行时常量池又被称为 Runtime Constant Pool,这块区域是方法区的一部分,它的名字非常有意思,通常被称为 非堆。它并不要求常量一定只有在编译期才能产生,也就是并非编译期间将常量放在常量池中,运行期间也可以将新的常量放入常量池中,String 的 intern 方法就是一个典型的例子。
  • 5、本地方法接口(native)(和本地方法库相连),同时这一层还有执行引擎

2.2. jvm垃圾回收

垃圾回收,指的的堆内存的垃圾回收,垃圾回收机制简称GC

程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经无法访问,程序用不了它们了,对程序而言它们已经死亡),为了确保程序运行时的性能,java虚拟机在程序运行的过程中不断地进行自动的垃圾回收(GC)。

垃圾收集系统是Java的核心,也是不可少的,Java有一套自己进行垃圾清理的机制,开发人员无需手工清理

9d4f28349422c9714bbcb35604bc08ff

为什么java栈,本地方法栈,程序计数器是不会有垃圾回收的?

因为他们是栈,最终是要出栈的,若是上面的是一个垃圾阻塞了,那他就无法出栈了,Jvm调优也就是垃圾回收,调的就是方法区和堆,99%是调堆。

手动执行GC

System.gc(); // 手动回收垃圾

finalize方法作用

  • 1、finalize()方法是在每次执行GC操作之前时会调用的方法,可以用它做必要的清理工作。

  • 2、它是在Object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。

public class Test {
	public static void main(String[] args) {
		Test test = new Test();
		test = null;
		System.gc(); // 手动回收垃圾
	}

	@Override
	protected void finalize() throws Throwable {
		// gc回收垃圾之前调用
		System.out.println("gc回收垃圾之前调用的方法");
	}
}

2.3. jvm调优

505a192a9f4b519eec155d0cfd56b0ca

二、类加载器

类加载器: 负责把class文件加载到内存中

类加载机制

Java 虚拟机负责把描述类的数据从 Class 文件加载到系统内存中,并对类的数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型,这个过程被称之为 Java 的类加载机制。

1. 类加载的过程

一个类从被加载到虚拟机内存开始,到卸载出内存为止,一共会经历下面这些过程。

798bd696514621e2b5ce1605840e61f4

类加载机制一共有五个步骤,分别是加载、链接、初始化、使用和卸载阶段,这五个阶段的顺序是确定的。

其中链接阶段会细分成三个阶段,分别是验证、准备、解析阶段,这三个阶段的顺序是不确定的,这三个阶段通常交互进行。解析阶段通常会在初始化之后再开始,这是为了支持 Java 语言的运行时绑定特性(也被称为动态绑定)。

1.1.加载

1、获取class文件加载成二进制字节流
2、把该文件的编码结构-->运行时的内存结构
3、在内存中生成该类的一个Class对象

1.2.链接

验证
	确保 Class 文件的字节流中的内容符合《Java虚拟机规范》中的要求
准备
	为类中的变量分配内存并设置其初始值
解析 
	相当于翻译的过程,Java虚拟机将常量池内的符号引用替换为直接引用的

1.3.初始化

类加载过程的最后一个步骤,在之前的阶段中,都是由 Java 虚拟机占主导作用,但是到了这一步,却把主动权移交给应用程序。

1.4.使用

初始化之后的代码由 JVM 来动态调用执行

1.5.卸载

当代表一个类的 Class 对象不再被引用,那么 Class 对象的生命周期就结束了,对应的在方法区中的数据也会被卸载。
    
JVM 自带的类加载器装载的类,是不会卸载的,由用户自定义的类加载器加载的类是可以卸载的。

2.类加载器的分类

  • 虚拟机自带 的加载器

  • 启动类加载器 - null,获取不到,底层c++编写,向上委托到这里

  • 扩展类加载器 - ExtClassLoder

  • 应用程序类加载器 - AppClassLoder

3.双亲委派机制

  • 1、类加载器接收到一个加载请求时,他会委派给他的父加载器,实际上是去他父加载器的缓存中去查找是否有该类,如果有就加载返回,如果没有则继续委派给父类加载,直到顶层类加载器。
  • 2、如果顶层类加载器也没有加载该类,则会依次向下查找子加载器的加载路径,如果有就加载返回,如果都没有,则会抛出异常。

image

4.沙箱安全机制

如果我们要编写一个和核心类库全限定命一模一样的类,JDK为了保证核心代码的一个安全 阻止你的代码和全限定名相同 
    
优点:保证原生JDK的安全,保证核心源代码 防止API被篡改,避免重复加载类

5.Native方法区

5.1. native

凡是使用了native关键字的,说明Java的作用范围已经达不到了,它会去调用底层的C语言的库。

  1. 进入本地方法栈。
  2. 调用本地方法接口。

5.2. 方法区

Method Area方法区(此区域属于共享区间,所有定义的方法的信息都保存在该区域)
方法区是被所有线程共享,所有字段、方法字节码、以及一些特殊方法(如构造函数,接口代码)也在此定义。

静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。

5.3. PC寄存器

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

6.java栈(虚拟机栈)

6.1. 栈的作用

栈是运行时的单位 程序如何运行 如何处理数据

栈内存,主管程序的运行,生命周期和线程同步;
线程结束,栈内存也就释放了,对于栈来说,不存在垃圾回收问题

6.2.栈帧

a.概念 
	每个线程都有自己的栈,栈中的数据以栈帧的格式存在,每个方法对应一个栈帧 
    
b.存储内容 
	局部变量表
		每个方法的局部变量,数组结构,存放的形参 
		没有线程安全问题 因为数据是线程私有的
	操作数栈
		根据指令进行入栈 出栈 
    
c.原理
	先进后出

6.3.栈存储的东西

8大基本类型、对象引用,实例的方法

6.4.五道面试题

1.举例栈溢出的情况

  • 1、函数中采用了很大的结构体,或者数组;
  • 2、有很深的函数调用,或者递归调用
  • 3、访问了非法的地址

通过-Xss1m调整栈空间

2.调整栈大小,就能保证不出现溢出吗?

不能

3.分配的栈内存越大越好吗?

不是

4.垃圾回收是否会涉及到虚拟机栈?

不会

5.方法中定义的局部变量是否线程安全?

是的

7.堆

堆内存的大小是可以调节的

7.1. 三种JVM

  1. Sun公司的HotSpot。(java -version查看)
  2. BEA的JRockit
  3. IBM的J9VM

7.2.堆的概述

一个JVM实例对应一个进程实例,一个JVM实例有一个运行时数据区(Runtime)

一个Runtime就有一个独立的方法区和堆

一个进程有多个线程,多个线程共享一个方法区和堆空间

一个线程拥有自己独立的程序计数器/本地方法栈/虚拟机栈

为了解决多个线程访问出现线程不安全问题–>TLAB(线程私有空间)

垃圾回收只会在堆(方法区)当中进行回收

7.3.堆内存中细分

image

主要区别在于jdk8以前是新生区、养老区、永久区。jdk8即以后使用元空间代替了永久区。

227ee50e966adf60e3b7e2088d9679dc

1.新生区

新生区又叫做伊甸园区,包括:伊甸园区、幸存0区、幸存1区。

新生区:老年区=1:2

新生区=eden:from:to 【谁空谁是to】

创建对象在eden

2.永久区

这个区域是常驻内存的。
用来存放JDK自身携带的Class对象、Interface元数据,存储的是Java运行时的一些环境或类信息~。
这个区域不存在垃圾回收
关闭JVM虚拟机就会释放这个区域的内存。

什么情况下,在永久区就崩了?

  • 一个启动类,加载了大量的第三方jar包。
  • Tomcat部署了太多的应用。
  • 大量动态生成的反射类;不断的被加载,直到内存满,就会出现OOM

3.老年区和元空间

什么是老年区和元空间??
方法区是一种规范,不同的虚拟机厂商可以基于规范做出不同的实现,老年区和元空间就是出于不同jdk版本的实现。
方法区就像是一个接口,老年区与元空间分别是两个不同的实现类。
只不过老年区是这个接口最初的实现类,后来这个接口一直进行变更,直到最后彻底废弃这个实现类,由新实现类—元空间进行替代。

jdk1.8之前:

694f8dbf7bb31c9833c915c137bc8285

jdk1.8以及之后:在堆内存中,逻辑上存在,物理上不存在(元空间使用的是本地内存)

796ca080b420c447170d30c6b7dc7351

4.常量池

在jdk1.7之前,运行时常量池+字符串常量池是存放在方法区中,HotSpot VM对方法区的实现称为永久代。

38f66c4b577cb78d826bea4f50a92e2f

在jdk1.7中,字符串常量池从方法区移到堆中,运行时常量池保留在方法区中。

881a3ef67d3040347e9c1c249237d6d0

jdk1.8之后,HotSpot移除永久代,使用元空间代替;此时字符串常量池保留在堆中,运行时常量池保留在方法区中,只是实现不一样了,JVM内存变成了直接内存。

e9892b982ef64b9edc2f013d8a068090

8.GC垃圾回收

8.1. 垃圾回收的区域

主要都是在方法区和堆中,且99%都是在堆中

8.2.引用计数法

每个对象在创建的时候,就给这个对象绑定一个计数器。每当有一个引用指向该对象时,计数器加一;每当有一个指向它的引用被删除时,计数器减一。这样,当没有引用指向该对象时,计数器为0就代表该对象死亡,这时就应该对这个对象进行垃圾回收操作。

优点:引用计数算法的实现简单,判定效率高,但建议不要使用

缺点:术无法解决对象之间的循环引用问题

24e10a4b449aa453a938d0c25786e921

8.3.复制算法

该算法将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。

这个算法与标记-整理算法的区别在于,该算法不是在同一个区域复制,而是将所有存活的对象复制到另一个区域内。

优点:在存活对象不多的情况下,性能高,能解决内存碎片和java垃圾回收算法之-标记清除 中导致的引用更新问题

缺点:会造成一部分的内存浪费。不过可以根据实际情况,将内存块大小比例适当调整;如果存活对象的数量比较大,复制算法的性能会变得很差

6c63c44718aba8c7ef44f536ec3d8145

7c45a21d5b193943ac2d08080e284e5a

8.4.标记清除算法

为每个对象存储一个标记位,记录对象的状态(活着或是死亡)。
分为两个阶段,一个是标记阶段,这个阶段内,为每个对象更新标记位,检查对象是否死亡;第二个阶段是清除阶段,该阶段对死亡的对象进行清除,执行 GC 操作。

优点:解决循环引用的问题、必要时才回收(内存不足时)

缺点:1、回收时,应用需要挂起,也就是stop the world;2、标记和清除的效率不高,尤其是要扫描的对象比较多的时候;3、会造成内存碎片(会导致明明有内存空间,但是由于不连续,申请稍微大一些的对象无法做到)

b00a1294d10389dd6af9de3fb6a56bdf

8.5.标记压缩算法

在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;不同的是,在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是将所有存活的对象整理一下,放到另一处空间,然后把剩下的所有对象全部清除。

优点:解决标记清除算法出现的内存碎片问题

缺点:压缩阶段,由于移动了可用对象,需要去更新引用

4b4022234c317444b03af09e036e5b54

8.6.GC算法总结

  • 内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)
  • 内存整齐度:复制算法=标记压缩算法>标记清除算法
  • 内存利用率:标记压缩算法=标记清除算法>复制算法

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

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

相关文章

别不信:这些细节关乎你的物联网设备的命运!

《高并发系统实战派》-- 值得拥有 一、设备接入层网络协议的意义 随着物联网的发展,越来越多的设备需要接入云平台进行远程监控和管理。设备接入层网络协议起到了承担设备接入网络的功能,为物联网平台提供了数据交互的基础。设备接入层网络协议对于物联…

【C++ 入坑指南】(01)学习路线

入门 1. 推荐书籍 《Accelerated C》,《Essential C》二选一精读。《A Tour of C》选读。 《Accelerated C》很适合新手,因为只有短短不到 300 页,在普遍一样的入门书籍里面是一股清流。容易通读完,减少挫败感。就这样的篇幅&am…

【每天学习一点新知识】如何绕过CDN查真实ip

1、什么是CDN 为了防止流量过大网络堵塞,我们就在靠近用户的地方,建一个缓存服务器,把远端的内容复制一份,放在这里,简单来说就是将内容缓存在终端用户附近。 2、怎么绕过cdn找到远端服务器的真实ip呢? &…

FS2462是泛海微自主开发的5A降压型同步整流芯片

FS2462是泛海微自主开发的5A降压型同步整流芯片,是国内首家大电流同步5A芯片,内部集成极低RDS内阻20豪欧金属氧化物半导体场效应晶体管的(MOSFET)。输入工作电压宽至4.75V到21V,输出电压1.0V可调至20V。5A的连续负载电流输出可保证系统各状态…

Landing AI:计算机视觉数据标注AI平台

【产品介绍】 Landing AI是一家由人工智能领域的知名专家、Coursera联合创始人、前百度首席科学家、Google大脑创始负责人吴恩达博士创立的公司,旨在为各行各业提供先进的计算机视觉解决方案。 Landing AI的核心产品是LandingLens,一个基于云端的计算机视…

前端开发代码规范工具

规范化是前端工程化的一个重要部分。现在,有许多工具能够辅助我们实行代码的规范化,比如你一定知道的 ESLint 和 Prettier。 今天,来聊聊这些工具的工作原理和基本使用,了解它们是如何发挥作用的,以及如何更好地利用这些工具去规…

AI成功破译古老未知语言,人工智能技术开辟历史研究新时代

近年来,人工智能在各个领域取得了突飞猛进的发展,成为了当今社会讨论的热点。尽管有关其使用的争议不断,但AI技术在某些方面的作用已经不容忽视。 最近,以色列特拉维夫大学和阿里尔大学的研究者们联手研发了一款能够破译古老未知…

Nature:刘清华团队揭示调控睡眠时间的关键分子通路

导读 你能做到一周不睡觉吗?良好的睡眠对我们保证生活质量十分重要。不过,有些人每天只需睡4-6个小时,有些人则需要8个小时(可能还不够),这是什么原因导致的? 其实,这也是很多科学…

阿里云服务器镜像是什么意思?

阿里云服务器镜像是云服务器的装机盘,镜像是为云服务器安装操作系统的。云服务器镜像系统怎么选择?云服务器操作系统镜像分为Linux和Windows两大类,Linux可以选择Alibaba Cloud Linux,Windows可以选择Windows Server 2022数据中心…

怎样恢复删除的视频?这5个方法才是正确答案!

案例:怎样恢复删除的视频? 【我是个视频爱好者,平常会在电脑中存很多视频,但也经常会将很多视频误删,怎样恢复删除的视频呢?希望大家给我一些建议!】 在摄影摄像技术较发达的今天,…

cond conv 代码-思想

参考博客: 1 解析图示最清楚动态卷积之CondConv思想和代码实现_&永恒的星河&的博客-CSDN博客 2 知乎的解释,简洁明了CondConv代码解析 - 知乎 知乎提供code:External-Attention-pytorch/CondConv.py at master xmu-xiaoma666/Extern…

详解MySQL索引失效

目录 B树结构 测试数据 索引失效的情况 没有用到索引 违反左前缀原则 范围查询断索引 like需要分情况 结果数据超过半数 B树结构 索引失效的根本原因其实就是违反了B树的结构特性,查找的时候没办法在B树上继续走下去,所以首先我们来回顾一下B树…

进程控制(中)

目录: 1.status获取子进程退出的退出码和信号 2.不进行位操作方式获取子进程的退出码和信号 3.waitpid 第三个参数options ------------------------------------------------------------------------------------------------------------------------------- 1.…

工业4.0,为什么数字化转型这么难,上了ERP还要上MES

工业4.0时代,中国制造企业已经面临着与国际先进水平的差距,更多的企业在寻找新的发展道路,数字化转型是制造业企业转型升级的必由之路。但是,许多制造型企业由于在传统生产过程中,业务数据不能得到有效监控、生产过程数…

人脸修复增强调研

Real-ESRGAN 工程地址:https://github.com/xinntao/Real-ESRGAN 效果: 人脸增强部分,调用的GFPGAN. GFPGAN 工程地址:https://github.com/TencentARC/GFPGAN 论文效果: BasicSR-ESRGAN: 项目地址&a…

巨杉数据库荣获新睿之星,赋能大湾区技术与产业升级

巨杉数据库凭借多年深耕分布式数据库的技术积累和创新能力,于广州投资年会上荣获新睿之星奖项,该奖项不仅是对巨杉数据库的肯定,也充分肯定广州培育本土高新企业的发展成果。 4月18日,2023年第九届广州国际投资年会在广州白云国际…

2023年10大最佳「内容日历」软件工具

随随便便运行一个社交媒体策略就能成功,这几乎是不可能。你需要提前规划排期,收集资源并与他人合作,来创造出能吸引受众注意力的内容。 所有这些规划、研究和创意都需要一个地方汇总聚合,这就是内容日历软件的用武之地。 有了合…

C++ 多线程:实现一个功能完整的线程池

C 多线程(四):实现一个功能完整的线程池 今天我们来聊一聊异步编程的知识。在分布式系统中,一个功能完整的线程池类是一切代码的前提。 一个『合格』的线程池该具备哪些功能? 首先,很自然地想到『线程池类…

被嫌弃可视化太丑?这种可视化大屏搭建方法,分分钟让老板满意

在数据可视化中,使用频率最高的展览方式一定是地图可视化。基本上现有的大屏都是以地图作为主视图来呈现的,没有一幅地图放到大屏中央,已经不好意思给同行说明自己企业数据分析有多牛了。在地图可视化中,最炫酷的一定是3D可视化大…

家用洗地机有什么推荐的吗?家用洗地机哪款好

洗地机是创新、高效的清洁工具,其具有高性能的清洁能力和卓越的操作体验。与传统的清洁工具相比,洗地机可以迅速而彻底地打扫地面,降低清洁时间和人力成本,让我们在工作之余不用花费大量的时间和精力去打扫卫生,下面就…