ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1.19分享

2022-01-19 11:59:48  阅读:147  来源: 互联网

标签:Java 虚拟机 1.19 线程 JVM 分享 class 加载


先思考一个问题

我们开发人员编写的Java代码是怎么让电脑认识的

Java文件编译的过程
1.程序员编写的.java文件
2.由javac编译成字节码文件.class:(为什么编译成class文件,因为JVM只认识.class文件)
3.在由JVM编译成电脑认识的文件 (对于电脑系统来说 文件代表一切)
在这里插入图片描述

回顾之前关于jvm的认识

为什么说java是跨平台语言

这个跨平台是中间语言(JVM)实现的夸平台-=
java有JVM从软件层面屏蔽了底层硬件、指令层面的细节让他兼容各种系统
在这里插入图片描述

Jdk和Jre和JVM的区别

  1. JDK:Java开发工具包(Java Development Kit),提供了Java的开发环境和运行环境。
  2. JRE:Java运行环境(Java Runtime Environment),提供了Java运行所需的环境。
  3. JVM : Java虚拟机

jvm

1 JVM运行时数据区

在这里插入图片描述

2 解析JVM运行时数据区

2.1 方法区(Method Area)

① 存放:类的元数据(描述类的信息)、常量池、方法信息(方法数据、方法代码)
② 它有个别命叫Non-Heap(非堆)。当方法区无法满足内存分配需求时,抛出OutOfMemoryError异常。

2.2 Java堆(Java Heap)

① 存放对象实例(数组、对象)
② 堆是jvm区域中最大的一块,在jvm启动时就已经创建完毕
③ java堆是垃圾收集器管理的主要区域,因此也被成为“GC堆”。
④ 无论怎么划分,都与存放内容无关,无论哪个区域,存储的都是对象实例,进一步的划分都是为了更好的回收内存,或者更快的分配内存。
⑤ 如果堆中没有内存可以完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

2.3 程序计数器(Program Counter Register)

① 程序计数器是一块较小的内存空间,它可以看作是:保存当前线程所正在执行的字节码指令的地址(行号)
② 2.程序计数器 是唯一一个 不会 产生 “内存溢出”的区域。
总结:也可以把它叫做线程计数器

在java中最小的执行单位是线程,线程是要执行指令的,执行的指令最终操作的就是我们的电脑,就是 CPU。在CPU上面去运行,有个非常不稳定的因素,叫做调度策略,这个调度策略是时基于时间片的,也就是当前的这一纳秒是分配给那个指令的。

假如:线程A在看直播
在这里插入图片描述
突然,线程B来了一个视频电话,就会抢夺线程A的时间片,就会打断了线程A,线程A就会挂起
在这里插入图片描述
然后,视频电话结束,这时线程A究竟该干什么?
(线程是最小的执行单位,他不具备记忆功能,他只负责去干,那这个记忆就由:程序计数器来记录)

在这里插入图片描述

2.4 Java虚拟机栈(Java Virtual Machine Stacks)

① 方法在执行的同时,会在虚拟机栈中创建一个栈帧
② 栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
③ 当方法太多时,就可能发生 栈溢出异常StackOverflowError,或者内存溢出异常OutOfMemoryError
在这里插入图片描述

  • 局部变量表:是用来存储我们临时8个基本数据类型、对象引用地址、returnAddress类型。(returnAddress中保存的是return后要执行的字节码的指令地址。)
  • 操作数栈:操作数栈就是用来操作的,例如代码中有个 i =
    6*6,他在一开始的时候就会进行操作,读取我们的代码,进行计算后再放入局部变量表中去
  • 动态链接:假如我方法中,有个 service.add()方法,要链接到别的方法中去,这就是动态链接,存储链接的地方。
  • 出口:出口是什呢,出口正常的话就是return,不正常的话就是抛出异常

2.5 本地方法栈(Native Method Stack)

① 原理和结构与虚拟机栈一致
② 不同点: 虚拟机栈中存放的 jdk或我们自己编写的方法,而本地方法栈调用的 操作系统底层的方法。

3.类的加载

程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。

Jvm执行class文件
在这里插入图片描述

3.1、加载

① 加载指的是将类的class文件读入到内存
② Java类加载器由JVM提供,是所有程序运行的基础,JVM提供的这些类加载器通常被称为系统类加载器。除此之外,开发者可以通过继承ClassLoader基类来创建自己的类加载器。

3.2、连接过程

  • 验证 .class 正确性校验,确保加载的类信息符合JVM规范,没有安全方面的问题。主要验证是否符合Class文件格式规范,并且是否能被当前的虚拟机加载处理。
  • 准备:正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
  • 解析:虚拟机常量池的符号引用替换为字节引用过程

3.3、初始化

① 给static变量 赋予正确的值
② 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化

static int num = 10 ; 在连接的准备阶段,会把num=0,之后(初始化阶段)再将0修改为10
这里不包含final修饰的static ,因为final在编译的时候就已经分配了。这里不会为实例变量分配初始化。

4.理解双亲委派模式

4.1 类加载器的介绍

  • 启动(Bootstrap)类加载器
  • 扩展(Extension)类加载器
  • 系统类加载器
  • 自定义加载器
    在这里插入图片描述

4.2 理解双亲委派模式

如果一个类收到了类加载的请求,它并不会自己先去加载,而是把这个请求委托给父类加载器去执行,如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最后到达顶层的启动类加载器,如果父类能够完成类的加载任务,就会成功返回,倘若父类加载器无法完成任务,子类加载器才会尝试自己去加载,这就是双亲委派模式。
在这里插入图片描述
就是每个儿子都很懒,遇到类加载的活都给它爸爸干,直到爸爸说我也做不来的时候,儿子才会想办法自己去加载。

4.3优势

① 通过这种层级关系可以避免类的重复加载,当父亲已经加载了该类的时候,就没有必要子类加载器(ClassLoader)再加载一次。
② 考虑到安全因素
Java核心API中定义类型不会被随意替换,假设通过网路传递一个名为java.lang.Integer的类,通过双亲委派的的模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字类,发现该类已经被加载,并不会重新加载网络传递过来java.lang.Integer.而之际返回已经加载过的Integer.class,这样便可以防止核心API库被随意篡改

标签:Java,虚拟机,1.19,线程,JVM,分享,class,加载
来源: https://blog.csdn.net/m0_47612445/article/details/122573150

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有