p7付费课程笔记:jvm基础知识、字节码、类加载器

news2024/11/24 8:30:30

编程语言

演化:

机器语言->编程语言->高级语言(java,c++,Go,Rust等)

面向过程–面向对象-面向函数

java是一种面向对象、静态类型、编译执行,有VM(虚拟机)/GC和运行时、跨平台的高级语言。重点:VM(虚拟机)/GC(Garbage Collector)和运行时、跨平台。
在这里插入图片描述

跨平台步骤:字节码文件被虚拟机加载(类加载器)加载到内存中,转换成具体的对象
在这里插入图片描述

字节码

结构:

Java byteCode由单字节(byte)指令构成,理论上最多支持256个操作码(opcode)。实际上java只使用了200左右的操作码,其他留给了调试操作。

根据指令的性质大概分为四大类:

1.栈操作指令,包括与局部变量交互的指令,

2.程序流程指令,

3.对象操作指令,比如方法调用的指令,

4.算数运算以及类型转换的指令,

运行步骤:
在这里插入图片描述

JVM是一个基于栈的计算机,每个线程都有独属于自己的线程栈(JVM Stack),用语存储栈帧。每次调用方法就会自动创建一个线程栈。栈帧是由操作数栈、局部变量表以及一个class引用组成,class引用中又包含着我们使用的常量池

操作demo:https://juejin.cn/post/7141206840456511496/

类加载器

类生命周期的七个步骤:

在这里插入图片描述

1.加载:找到class文件;

2.验证:验证字节码文件格式是否正确、依赖是否完备;

3.准备:静态字段、方法表;

4.解析:符合解析为引用;

5.初始化:构造器,静态变量赋值,静态代码块;

6.使用

7.卸载

前五步是我们通常所说的类加载过程,其中2、3、4可以合在一起称为-链接:

1 找到class文件,读出来2 验证格式,解析字段方法,所有符号转化为实际引用3 类相关初始化

类的加载时机:

虚拟机规范中并没有强制约束何时进行加载,但是规范严格规定了有且只有下列五种情况必须对类进行初始化(加载、验证、准备都会随着发生):

1.3.1 遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时,如果类没有进行过初始化,则必须先触发其初始化。最常见的生成这 4 条指令的场景是:使用 new 关键字实例化对象的时候;读取或设置一个类的静态字段(被 final 修饰、已在编译器把结果放入常量池的静态字段除外)的时候;以及调用一个类的静态方法的时候。

1.3.2 使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行初始化,则需要先触发其初始化。

1.3.3当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

1.3.4 当虚拟机启动时,用户需要指定一个要执行的主类(包含 main() 方法的那个类),虚拟机会先初始化这个主类;

1.3.5 当使用 JDK.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果为 REF_getStatic, REF_putStatic, REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化;

以上 5 种场景中的行为称为对一个类进行主动引用。除此之外,所有引用类的方式都不会触发初始化,称为被动引用。被动引用的常见例子包括:

通过子类引用父类的静态字段,不会导致子类初始化。

通过数组定义来引用类,不会触发此类的初始化。该过程会对数组类进行初始化,数组类是一个由虚拟机自动生成的、直接继承自 Object 的子类,其中包含了数组的属性和方法。

常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。

总结:显式,隐式隐式,子类父类,实现类和接口,反射,动态调用显式,main方法,new,静态字段和方法

三类加载器和特点:

在这里插入图片描述

1.启动类加载器(BootstrapClass Loader)

这个类加载使用C/C++语言实现,嵌套在JVM内部

它用来加载JAVA的核心库(JAVA_HOME/jre/lib/rt.jar,resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类

并不继承自Java.lang.ClassLoader,没有父加载器

加载扩展类和应用程序类加载器,并指定为它们的父类加载器

出于安全考虑,Bootstrap启动类加载器只加载包名为java,javax,sun等开头的类

启动类加载器不像其他类加载器有实体,它是没有实体的,JVM将C++处理类加载的一套逻辑定义为启动类加载器。因此,启动类加载器是无法被Java程序调用的。

2.扩展类加载器(Extension Class Loader)

java语言编写,由sun.misc.Launcher$ExtClassLoader实现

派生于ClassLoader类

父类加载器为启动类加载器

从Java.ext.dirs系统属性所指的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

public static void main(String[] args) {
    ClassLoader classLoader = ClassLoader.getSystemClassLoader().getParent();

    URLClassLoader urlClassLoader = (URLClassLoader) classLoader;

    URL[] urls = urlClassLoader.getURLs();
    for (URL url : urls) {
        System.out.println(url);
    }
}

3.应用程序加载器(系统类加载器,System Class Loader/App Class Loader)

java语言编写,由sun.misc.Launcher&AppClassLoader实现

派生于ClassLoader类

父类加载器为扩展类加载器

它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库

该类加载是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载

通过ClassLoader#getSystemClassLoader()方法可以获得到该类加载器

public static void main(String[] args) {
    String[] urls = System.getProperty("java.class.path").split(":");

    for (String url : urls) {
        System.out.println(url);
    }

    System.out.println("================================");

    URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

    URL[] urls1 = classLoader.getURLs();
    for (URL url : urls1) {
        System.out.println(url);
    }
}

4.用户自定义类加载器

在Java的日常应用程序开发中,类加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。

1、开发人员可以通过继承抽象类java.lang.classLoader类的方式,实现自己的类加载器,以满足一些特殊的需求

2、在JDK2.0之前,在自定义类加载器时,总会去继承classLoader类并重写loadclass ()方法,从而实现自定义的类加载类,但是在JDK2.0之后已不再建议用户去覆盖loadclass ()方法,而是建议把自定义的类加载逻辑写在findclass ()方法中

3、在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findclass ()方法及其获取字节码流的方式,这样会让自定义类加载器编写更为简单一些。

在这里插入图片描述

双亲委派

双亲委派机制的原理:

如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行。

如果父类的加载器还存在其父类加载器,则进一步向上委托,依次递归请求最终达到顶层的启动类加载器。

如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派机制。

优点:

避免类的重复加载,确保一个类的全局唯一性

保护程序安全,防止核心API被随意篡改

缺点:

无法做到不委派,无法做到向下委派

在某些场景下双亲委派制过于局限,所以有时候必须打破双亲委派机制来达到目的。例如:SPI机制,这个SPI机制涉及到打破双亲委派机制,工作中没有涉及到就不细说了,感兴趣的同学可以自己研究下。

双亲委派在JVM中的实现代码:

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        // First, check if the class has already been loaded
        // 首先,去检查类是否已经被加载
        Class<?> c = findLoadedClass(name);
        // 如果类还未被加载
        if (c == null) {
            long t0 = System.nanoTime();
            try {
                // 获取父类加载器加载该类
                if (parent != null) {
                    // this 是AppClassLoader, this.parent是ExtClassLoader
                    c = parent.loadClass(name, false);
                } else {
                    c = findBootstrapClassOrNull(name);
                }
            } catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        // 判断类是否被解析
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}

这一期的课程大概就讲了这么多吧,说实话看完还是好多记不住和不理解,也是反复记忆并且查了好多资料才知道,所以不理解很正常,没有接触过就能一遍看懂的一般都是高级及以上了,慢慢看就可以了。看一点就是进步。

下期这周末写,大概是内存模型和JMM的相关知识,小伙伴可以先复习下,然后查漏补缺。

今天就到这里吧,感觉有用的小伙伴可以点个赞,你的支持就是我更新的最大动力!

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

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

相关文章

第二章 视觉感知与视觉通道(复习)

大纲 视觉感知 认知 视觉通道 色彩* 可视化致力于外部认知&#xff0c;也就是说&#xff0c;怎样利用大脑以外的资源来增强大脑本身的认知能力。 感知是指客观事物通过人的感觉器官在人脑中形成的直接反映 感觉器官&#xff1a;眼、耳、口、鼻、神经末梢 视觉感知就是客观事物通…

世界史上五个横跨亚欧非三大洲的超强帝国

古代地中海和西亚地区文明出现的很早&#xff0c;经济文化社会都比较先进&#xff0c;其中古埃及早在四千多年前就建立了庞大的帝国&#xff0c;给世人留下了不朽的金字塔&#xff1b;两河流域、希腊半岛也很早就出现了城邦制的国家&#xff0c;也创造了灿烂的文明。同时&#…

架构设计我们要注意什么?

这几天我正在做一个新项目的架构设计&#xff0c;关于动态流程引擎平台的搭建&#xff0c;涉及到了系统架构的设计&#xff0c;里面涉及了方方面面&#xff0c;所以就想着结合自己的实际经验&#xff0c;遇到的问题&#xff0c;以及自己的理解&#xff0c;为大家做一个简单的分…

损失函数:IoU、GIoU、DIoU、CIoU、EIoU、alpha IoU、SIoU、WIoU超详细精讲及Pytorch实现

前言 损失函数是用来评价模型的预测值和真实值不一样的程度&#xff0c;损失函数越小&#xff0c;通常模型的性能越好。不同的模型用的损失函数一般也不一样。 损失函数的使用主要是在模型的训练阶段&#xff0c;如果我们想让预测值无限接近于真实值&#xff0c;就需要将损…

献给蓝初小白系列(二)——Liunx应急响应

1、Linux被入侵的症状​​ ​​https://blog.csdn.net/weixin_52351575/article/details/131221720​​ 2、Linux应急措施 顺序是&#xff1a;隔离主机--->阻断通信--->清除病毒--->可疑用户--->启动项和服务--->文件与后门--->杀毒、重装系统、恢复数据 …

python代码加密方案

为何要对代码加密&#xff1f; python的解释特性是将py编译为独有的二进制编码pyc 文件&#xff0c;然后对pyc中的指令进行解释执行&#xff0c;但是pyc的反编译却非常简单&#xff0c;可直接反编译为源码&#xff0c;当需要将产品发布到外部环境的时候&#xff0c;源码的保护尤…

Guitar Pro是什么软件 Guitar Pro有什么用

相信玩吉他的朋友多多少少都听说过Guitar Pro这款软件&#xff0c;那大家知道Guitar Pro是什么软件&#xff1f;Guitar Pro有什么用呢&#xff1f;今天小编就和大家分享一下关于Guitar Pro这款吉他软件的相关内容。 一、Guitar Pro是什么软件 简单说Guitar Pro是一款吉他谱软…

Vue实现元素沿着坐标数组移动,超出窗口视图时页面跟随元素滚动

一、实现元素沿着坐标数组移动 现在想要实现船沿着下图中的每个河岸移动。 实现思路&#xff1a; 1、将所有河岸的位置以 [{x: 1, y: 2}, {x: 4, y: 4}, …] 的形式保存在数组中。 data() {return {coordinateArr: [{ x: 54, y: 16 }, { x: 15, y: 31 }, { x: 51, y: 69 }…

leetcode77. 组合(回溯算法-java)

组合 leetcode77. 组合题目描述解题思路代码演示 递归专题 leetcode77. 组合 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/combinations 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个…

量化交易:止盈策略与回测

我们买基金或股票的时候通常用最简单的策略进行决策&#xff1a;低买高卖&#xff0c;跌的多了就加仓拉低持有成本&#xff0c;达到收益率就卖出。 那么如何用代码表示这个策略呢&#xff1f;首先定义交易信号则是&#xff1a;0.5%时买入&#xff0c;目标止盈线是1.5%&#xf…

Java官方笔记12异常

Exception Definition: An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the programs instructions. the checked exception 比如&#xff0c;java.io.FileNotFoundException the error 比如&#xff0c;java.i…

Flink流批一体计算(2):Flink关键特性

目录 流式处理 丰富的状态管理 流处理 自定义时间流处理 有状态流处理 通过状态快照实现的容错 流式处理 在自然环境中&#xff0c;数据的产生原本就是流式的。无论是来自 Web 服务器的事件数据&#xff0c;证券交易所的交易数据&#xff0c;还是来自工厂车间机器上的…

优先级队列建立小根堆来解决前K个高频元素(TOP K问题)

目录 场景一&#xff1a;解决前K个高频元素需要解决如下几个问题&#xff1a; 优先级队列PriorityQueue 堆的定义 题目链接 场景二&#xff1a;亿万级数据取前TOP K / 后TOP K 数据 场景一&#xff1a;解决前K个高频元素需要解决如下几个问题&#xff1a; 1.记录每一个元…

【C++】4.工具:读取ini配置信息

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍读取ini配置信息。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&…

医院PACS系统的发展历史

PACS全称Picture Archivingand Communication Systems。它是应用在医院影像科室的系统&#xff0c;主要的任务就是把日常产生的各种医学影像&#xff08;包括核磁&#xff0c;CT&#xff0c;超声&#xff0c;X光机&#xff0c;红外仪、显微仪等设备产生的图像&#xff09;通过各…

【工程应用八】终极的基于形状匹配方案解决(小模型+预生成模型+无效边缘去除+多尺度+各项异性+最小组件尺寸)...

我估摸着这个应该是关于形状匹配或者模版匹配的最后一篇文章了&#xff0c;其实大概是2个多月前这些东西都已经弄完了&#xff0c;只是一直静不下来心整理文章&#xff0c;提醒一点&#xff0c;这篇文章后续可能会有多次修改(但不会重新发文章&#xff0c;而是在后台直接修改或…

【MySQL 日志管理、备份与恢复】

目录 一、数据库备份的分类1、从物理与逻辑的角度1.1、物理备份: 对数据库操作系统的物理文件&#xff08;如数据文件&#xff0c;日志文件等&#xff09;的备份1.2、逻辑备份 2、从数据库的备份策略角度3、常见的备份方法3.1、物理冷备3.2、专用备份工具mysqldump 或者 mysqlh…

【Windows系统】windows服务

概述 Microsoft Windows 服务&#xff08;即&#xff0c;以前的 NT 服务&#xff09;使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动&#xff0c;可以暂停和重新启动而且不显示任何用户界面。这种服务非常适合在服…

C++算法:多源最短路径(Floyd)

文章目录 前言一、Floyd算法二、代码实现总结 前言 前文单源最短路径Dijkstra中我们讨论了如何解决有向无环图的最短路径问题&#xff0c;Dijkstra只能解决一个起始点的问题&#xff0c;如果要解决每个顶点到任一顶点的最短路径呢&#xff1f;一个方法就是再循环一次&#xff…

ASEMI代理光宝高速光耦LTV-60L规格,LTV-60L封装

编辑-Z LTV-60L参数描述&#xff1a; 型号&#xff1a;LTV-60L 封装&#xff1a;LSOP-6 储存温度TST&#xff1a;-55~125℃ 工作温度TA&#xff1a;-40~105℃ 隔离电压VISO&#xff1a;5000VRMS 电源电压VCC&#xff1a;7V 平均正向输入电流IF&#xff1a;20mA 输入功…