Java虚拟机介绍

8620d716b7f14ca691b4d48cea132948.jpg

 

JVM是一种用于计算设备的规范,它是一个虚拟出来的计算机,是通过在实际的计算机上仿真模拟计算机的各个功能来实现的。Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。每个Java虚拟机都着一个清晰的任务:执行Java程序。程序执行时虚拟机才启动,程序结束时它才停止。

 

JVM的生命周期?

启动。启动一个Java程序的时候,就产生了一个JVM实例。

运行。main方法是程序的入口,任何其他线程均有它启动。

消亡。当程序中所有非守护线程都终止时,JVM才退出。若安全管理器允许,程序也可以使用Runtime类或者System.exit()来退出程序。

Java中的线程

Java中的线程分为两种:守护线程(daemon)和普通线程(non-daemon)。守护线程是JVM自己使用的的线程,如GC。当然也可以自己设置守护线程,但包含main方法的初始线程不是守护线程。

只要JVM中还有普通线程在执行,JVM就不会停止。但如果有足够的权限,可以调用exit方法终止程序。

 

JVM的体系结构

类装载器(ClassLoader,用来装载.class文件)

执行引擎(执行字节码或本地方法)

运行时数据区(方法区、堆区、虚拟机栈、本地方法栈、程序计数器)

JVM类的加载机制

Java程序并不一个可执行文件,是由多个独立的类文件组成。这些类文件并非一次性全部装入内存,而是依据程序逐步载入。

 

JVM的类加载是通过ClassLoader及其子类类完成的,类的层次关系和记载顺序可以由下图说明:

 

 

Bootstrap ClassLoader

JVM的根ClassLoader,使用C++语言实现

使用它加载Java的核心API:$JAVA_HOME/jre/lib/rt.jar,这个jar中包含了java规范定义的所有接口以及实现。

JVM启动时即初始化此ClassLoader

Extension ClassLoader

加载Java的扩展API(lib/ext中的类)

App ClassLoader

加载classpath目录下的class

Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据J2EE规范自行实现ClassLoader

类在加载之前会先被检查是否已被加载,检查下的顺序是自底向上,从Custom ClassLoader到Bootstrap ClassLoader逐层检查,只要某个ClassLoader检查到已加载就视为此类已加载。从而保证类只加载一次。 而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。

 

双亲委派机制

JVM在加载类时默认采用的是双亲委派机制。

通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归。如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。

 

 

为什么使用这种机制

避免了类被重复加载

更安全。如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了。(为什么?因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader。)所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。

破坏双亲委派机制

双亲委派机制并不是一种强制性的约束模型,而是Java设计者推荐给开发者的类加载器实现方式。

 

线程上下文类加载器,这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那么这个类加载器就是应用程序类加载器。像JDBC就是采用了这种方式。这种行为就是逆向使用了加载器,违背了双亲委派模型的一般性原则。

 

类加载机制总结

 

 

JVM运行时数据区

 

 

堆区(Heap)

被所有线程共享的一块内存区域,在虚拟机启动时创建

用来存储对象实例

可以通过-Xms和-Xmx控制堆空间的大小

OutOfMemory: 当堆中没有完成实例分配,且堆再也无法扩展时。

JVM堆是垃圾收集器管理的主要区域。

堆空间还可细分为:

 

新生代(Eden/Young)[s0、s1]

年老代(Tenured/Old)

持久代(Permanent),在方法区,不属于堆

新生代: 新建的对象都有新生代分配内存。新生代常常又被划分为Eden和Survivor区,Eden空间不足时会把存活的对象转移到Survivor。新生代的大小可以使用-Xmn控制,也可用-XX:SurvivorRatio控制Eden和Survivor的比例。

 

年老代: 存放经过多次垃圾回收依然存活的对象

 

持久代: 存放静态文件,如今Java类、方法等。持久代在方法区,对垃圾回收没有显著影响。

 

方法区(Meta Space)

线程间共享

 

用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据等

 

OutOfMemoryError:当方法区无法满足内存分配时

 

运行时常量池

 

方法区的一部分

用于编译期生成的各种字面量与符号引用,如String类型的引用就存放在字符串常量池

OutOfMemoryError:当常量池无法在申请到内存时

Java虚拟机栈(VM Stack)

线程私有,生命周期与线程相同

存储方法的局部变量表(基本类型、对象引用)、操作数栈、动态链接、方法出口等信息

Java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧,每个方法被调用直至完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

StackOverflowError:当线程请求的栈深度大于虚拟机所允许的深度

OutOFMemoryError:如果栈的扩展时无法申请到足够的内存

JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量、部分的返回结果以及Stack Frame。其他引用类型的对象在JVM栈上仅存放变量名和指向堆上对象实例的首地址。

 

本地方法栈(Native Method Stack)

与虚拟机栈相似,主要是为虚拟机使用到的本地方法服务,在HotSpot虚拟机中和虚拟机栈合二为一

程序计数器(Programma Counter Register)

当前线程所执行的字节码的行号指示器

当前线程私有

不会出现OutOfMemoryError

直接内存(Direct Memory)

直接内存并不是虚拟机运行的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分内存也被频繁使用

NIO可以使用Native函数库直接分配堆外内存,堆中的DirectByteBuffer对象作为这块内存的引用进行操作

大小不受Java堆大小的限制,受本机(服务器)内存限制

OutOfMemoryError异常:系统内存不足时

总结:

 

Java对象实例存放在堆中,常量存放在方法区的常量池;

虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据存放在方法区;

以上区域是线程共享的

栈是线程私有的,存放该方法的局部变量表(基本类型、对象引用)、操作数栈、动态链接、方法出口等信息。

一个Java程序对应着一个JVM实例,一个方法(线程)对应一个虚拟机栈

Java代码的编译和执行过程

Java代码的编译和执行包括了三个重要机制:

(1)Java源码编译机制(.java -> .class)

(2)类加载机制(ClassLoader)

(3)类执行机制(执行引擎)

 

Java源码编译机制

Java源代码是不能被机器识别的,需要先经过编译器编译成JVM可以执行的.class字节码文件,再由解释器解释运行。

即:Java源文件(.java) -- Java编译器 --> Java字节码文件 (.class) -- Java解释器 --> 执行。

 

字节码文件(.class)是平台无关的

 

Java中字符只以一种形式存在:Unicode。字符转换发生在JVM和OS交界处(Reader/Writer)

 

最后生成的class文件由以下部分组成:

 

结构信息。包括class文件格式版本号及各部分的数量与大小的信息

元数据。对应于Java源码中声明与常量的信息。包含类/继承的超类/实现的接口的声明信息、域与方法声明信息和常量池

方法信息。对应Java源码中语句和表达式对应的信息。包含字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息

类加载机制在上面已经提到

 

类执行机制

Java字节码的执行是由JVM执行引擎来完成,流程图如下所示:

 

 

JVM是基于栈的体系结构来执行class字节码的。

线程创建后,都会产生程序计数器(PC)和栈(Stack),程序计数器存放下一条要执行的指令在方法内的偏移量,栈中存放一个个栈帧,每个栈帧对应着每个方法的每次调用,而栈帧又是有局部变量区和操作数栈两部分组成,局部变量区用于存放方法中的局部变量和参数,操作数栈中用于存放方法执行过程中产生的中间结果。

 

主要的执行技术:解释,即时编译,自适应优化、芯片级直接执行

 

解释属于第一代JVM

即时编译JIT属于第二代JVM

自适应优化(目前Sun的HotspotJVM采用这种技术)则吸取第一代JVM和第二代JVM的经验,采用两者结合的方式

开始对所有的代码都采取解释执行的方式,并监视代码执行情况。对那些经常调用的方法启动一个后台线程,将其编译为本地代码,并进行优化。若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行。

 

JVM垃圾回收

GC的基本原理:将内存中不再被引用的对象进行回收,GC中用于回收的方法称为收集器。垃圾:不再被引用的对象。

 

由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征进行分析后,按照新生代、旧生代的方式来对对象进行收集,以尽可能的缩短GC对应用造成的暂停。

 

对新生代的对象的收集称为minor GC

对旧生代的对象的收集称为Full GC

程序中主动调用System.gc()的GC为Full GC

 Java垃圾回收是单独的后台线程gc执行的,自动运行无需显示调用。即使主动调用了java.lang.System.gc(),该方法也只会提醒系统进行垃圾回收,但系统不一定会回应,可能会不予理睬。

 

判断一块内存空间是否符合回收标准:

 

对象引用赋予了空值,且之后再未调用(obj = null;)

对象引用赋予了新值,即重新分配了内存空间(obj = new Obj();)

内存泄漏: 程序中保留着对永远不再使用的对象的引用。因此这些对象不回被GC回收,却一直占用内存空间却毫无用处。

即:1)对象是可达的;2)对象是无用的。满足这两个条件即可判定为内存泄漏。

 

  应确保不需要的对象不可达,通常采用将对象字段设置为null的方式,或从容器collection中移除对象。局部变量不再使用时无需显示设置为null,因为对局部变量的引用会随着方法的退出而自动清除。

 

内存泄露的原因: 1)全局集合;2)缓存;3)ClassLoader

 

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

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

相关文章

用通俗易懂的方式讲解大模型:在 CPU 服务器上部署 ChatGLM3-6B 模型

大语言模型(LLM)的量化技术可以大大降低 LLM 部署所需的计算资源,模型量化后可以将 LLM 的显存使用量降低数倍,甚至可以将 LLM 转换为完全无需显存的模型,这对于 LLM 的推广使用来说是非常有吸引力的。 本文将介绍如何…

Flume基础知识(三):Flume 实战监控端口数据官方案例

1. 监控端口数据官方案例 1)案例需求: 使用 Flume 监听一个端口,收集该端口数据,并打印到控制台。 2)需求分析: 3)实现步骤: (1)安装 netcat 工具 sudo yum …

SVN服务端的下载、安装

地址 : Apache Subversion Binary Packages 下载 点击 VisualSVN 安装 都是点击 next 点击next ,即可安装成功

SpringBoot学习(三)-员工管理系统开发(重在理解)

注:此为笔者学习狂神说SpringBoot的笔记,其中包含个人的笔记和理解,仅做学习笔记之用,更多详细资讯请出门左拐B站:狂神说!!! 本文是基于狂神老师SpringBoot教程中的员工管理系统从0到1的实践和理解。该系统应用SpringB…

B端产品经理学习-需求挖掘

B端产品需求挖掘 目录 识别和管理干系人 决策人和负责人需求挖掘 针对用户进行需求挖掘 用户访谈结果整理 B端产品的需求来源是非常复杂的,要考虑多个方面;如果你是一个通用性的产品,要考虑市场、自身优劣势、干系人。而定制型B端产品会…

uniapp:签字版、绘画板 插件l-signature

官方网站:LimeUi - 多端uniapp组件库 使用步骤: 1、首先从插件市场将代码下载到项目 海报画板 - DCloud 插件市场 2、下载后,在项目中的uni_modules目录 3、最后 没有其它步骤,直接官网代码复制到vue文件中就可以了&#xff0c…

综合跨平台全端ui自动化测试框架Airtest——AirtestIDE录制微信小程序脚本教学

前言 有在自动化测试领域的小伙伴应该都知道,app和小程序自动化这一类的自动化测试在实际操作中有时候很棘手让人心烦,动不动就是用appium写代码脚本维护什么的,不仅步骤繁琐,环境配置方面也是繁琐无比,动不动就与客户…

[足式机器人]Part2 Dr. CAN学习笔记-动态系统建模与分析 Ch02-1+2课程介绍+电路系统建模、基尔霍夫定律

本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-动态系统建模与分析 Ch02-12课程介绍电路系统建模、基尔霍夫定律 1. 课程介绍2. 电路系统建模、基尔霍夫定律 1. 课程介绍 2. 电路系统建模、基尔霍夫定律 基本元件: 电量 库伦&…

多模态——旷视大模型Vary更细粒度的视觉感知实现文档级OCR或图表理解

概述 现代大型视觉语言模型(LVLMs),例如CLIP,使用一个共同的视觉词汇,以适应多样的视觉任务。然而,在处理一些需要更精细和密集视觉感知的特殊任务时,例如文档级OCR或图表理解,尤其…

前缀和算法 -- 寻找数组的中心坐标

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 本题链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 输入描述 给定一个数组&#xff0c;接口为int pivotIndex(vector<int>& nums) 输出描述 我们以示例1为例画图解释&#xf…

DRF从入门到精通七(djangorestframework-simplejwt、定制返回格式、多方式登录)

文章目录 一、djangorestframework-simplejwt快速使用1.基础使用步骤2.自己配置视图校验访问局部配置认证及权限类全局配置认证及权限类 3.关于双token认证问题 二、定制返回格式三、多方式登录 一、djangorestframework-simplejwt快速使用 JWT主要用于签发登录接口需要配合认证…

频谱论文:约束飞行轨迹下基于生成对抗网络的三维无线电地图重构

#频谱# T. Hu, Y. Huang, J. Chen, Q. Wu and Z. Gong, "3D Radio Map Reconstruction Based on Generative Adversarial Networks Under Constrained Aircraft Trajectories," in IEEE Transactions on Vehicular Technology, vol. 72, no. 6, pp. 8250-8255, June …

Vue - 多行文本“展开、收起”功能

TextClamp 使用 js 实现文本展开、收起&#xff0c;并非纯 CSS 实现。 Props&#xff1a; fontSize&#xff1a;Number&#xff0c;默认&#xff1a;14lines&#xff1a;Number&#xff0c;默认&#xff1a;1lineHeight&#xff1a;Number&#xff0c;默认&#xff1a;20 F…

字符编码转换

宽窄字符和字符编码的关系 多字节(窄)字符&#xff1a;在C/C中&#xff0c;char是一种数据类型&#xff0c;规定sizeof(char)1&#xff0c;即一个char占用一个字节&#xff0c;1Byte8bit。并没有规定一个char就要与ASCII对应&#xff0c;不过&#xff0c;通常情况下char值与AS…

2023 年博客总结

当无所事事&#xff0c;没有多少收获的时候&#xff0c;时间过得格外的快… 当充实有为&#xff0c;经常有收获有进步的时候&#xff0c;才觉得时间没有浪费… 2023年收获不多… 以前说孩子小&#xff0c;需要照顾所以没时间&#xff0c;我以为孩子大点就有时间了&#xff0c;…

图片处理相关网站(图片分辨率、尺寸修改、AI扩图等)

分享一些免费的可进行图片的各种处理的网站&#xff0c;包括图片分辨率、尺寸修改、AI扩图等&#xff0c;持续增加中。。。 1.photokit.com 可进行图片分辨率、尺寸、压缩等修改。 免费在线图片编辑器 - 在线抠图、改图、修图、美图 - PhotoKit.comPhotoKit是一款免费的…

【RocketMQ每日一问】RocketMQ SQL92过滤用法以及原理?

1.生产端 public class SQLProducer {public static int count 10;public static String topic "xiao-zou-topic";public static void main(String[] args) {DefaultMQProducer producer MQUtils.createLocalProducer();IntStream.range(0, count).forEach(i -&g…

自动化测试面试题及答案大全(上)

selenium中如何判断元素是否存在&#xff1f; 没有提供原生的方法判断元素是否存在&#xff0c;一般我们可以通过定位元素异常捕获的方式判断selenium中hidden或者是display &#xff1d; none的元素是否可以定位到&#xff1f; 不可以&#xff0c;想点击的话&#xff0c;可以用…

[ASIS 2019]Unicorn shop

点入题目看见四个可购买的东西&#xff0c;但是都购买不了&#xff0c;最后一个价格大的脱俗&#xff0c;猜测成功买到后会得到flag&#xff0c;但是购买时提示操作失败只允许一个字符。查看源码发现在utf-8后面特意标注提示 涉及到了字符编码和字符集的概念&#xff1a; UTF-…

2024 年度 AAAI Fellows 揭晓!清华大学朱军教授入选!

今日&#xff0c;国际人工智能领域最权威的学术组织 AAAI 揭晓 2024 年度 Fellows 评选结果&#xff0c;新增 12 位 Fellow。 其中&#xff0c;清华大学计算机系教授朱军因「在机器学习理论与实践方面做出的重大贡献」而成功入选&#xff0c;成为本年度入选的唯一华人学者&…