JVM 调优篇1 类的加载器与加载过程

一  基本知识

1.1 JIT&AOT

JIT:  Just Time compilation  即时编译器

在程序运行时将字节码或中间表示转换为机器代码。

AOT: Ahead of  Tmie  Compilation : 预编译

在程序运行之前将高级语言代码完全编译成机器代码。

1.2 字面量和符号引用*

字面量:在java中,字面量是指在代码中直接出现具体的值,如 String str=“123”;

符号引用:是对某个方法、字段或类的引用,这个引用指向元数据的引用。

public class Jia
{int field;void method(){}public static void main(String[] args) {Jia j = new Jia();j.field = 33;//字段引用j.method();//方法引用}
}

field是对类的字段的符号引用,method()是对类的方法的符号引用。这些引用指向的是元数据,而不是具体的值。

二  类的加载

2.1 jvm的类加载器*

ClassLoader是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部,转换为一个与目标类对应的java.lang.Class对象实例。然后交给Java虚拟机进行链接、初始化等操作。

类加载器分类:

1)启动类加载器(引导类加载器,Bootstrap ClassLoader)

这个类加载使用C/C++语言实现的,嵌套在JVM内部。它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下的内容)。用于提供JVM自身需要的类。

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

出于安全考虑,Bootstrap启动类加载器只加载包名为java、javax、sun等开头的类。加载扩展类和应用程序类加载器,并指定为它们的父类加载器。

 2)扩展类加载器(Extension ClassLoader)

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

继承于ClassLoader类;父类加载器为启动类加载器

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

3)应用程序类加载器(系统类加载器,AppClassLoader)

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

继承于ClassLoader类;父类加载器为扩展类加载器

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

应用程序中的类加载器默认是系统类加载器。它是用户自定义类加载器的默认父加载器

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

4)用户自定义类加载器

自定义类加载器体现Java语言强大生命力和巨大魅力的关键因素之一便是:Java开发者可以自定义类加载器来实现类库的动态加载,加载源可以是本地的JAR包,也可以是网络上的远程资源。

所有用户自定义类加载器通常需要继承于抽象类java.lang.ClassLoader。

通过类加载器可以实现非常绝妙的插件机制

自定义加载器能够实现应用隔离

5)获取类的加载器

2.2 Class.forName与Class.getClassLoader()的区别与联系?

Class.forName():是一个静态方法,最常用的是Class.forName(String className);根据传入类的全路径包名,返回一个 Class 对象。该方法在将 Class文件加载到内存的同时,会执行类的初始化。

如: Class.forName("com.atguigu.java.HelloWorld");

ClassLoader.loadClass():这是一个实例方法,需要一个 ClassLoader 对象来调用该方法。该方法将 Class 文件加载到内存时,并不会执行类的初始化,直到这个类第一次使用时才进行初始化。该方法因为需要得到一个 ClassLoader 对象,所以可以根据需要指定使用哪个类加载器。

如:ClassLoader cl=.......;    cl.loadClass("com.atguigu.java.HelloWorld");

String.class.getClassLoader().loadClass() 与Class.forName()的区别_.class.getclassloader();会调用loadclass方法吗-CSDN博客

2.3 类的双亲委托策略

类加载器用来把类加载到Java虚拟机中,类的加载过程采用双亲委派机制,这种机制能更好地保证Java平台的安全。

如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回。只有父类加载器无法完成此加载任务时,才自己去加载。

优点:

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

Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关系可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。

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

缺点:

检查类是否加载的委托过程是单向的,这个方式虽然从结构上说比较清晰,使各个ClassLoader的职责非常明确,但是同时会带来一个问题,即顶层的ClassLoader无法访问底层的ClassLoader所加载的类。

2.4 编译后不包含<clinit>方法

java编译器在以下情况,经过编译字节码后,文件不包含<clinit>方法

1)一个类中并没有声明任何的类变量,也没有静态代码块时。

2)一个类中声明类变量,但是没有明确使用类变量的初始化语句以及静态代码块来执行初始化操作时

3)一个类中包含static final修饰的基本数据类型的字段,这些类字段初始化语句采用编译时常量表达式。

如截图所示:

2.5 初始化阶段与链接-准备阶段

 static+final修饰的成员变量,为全局常量;给全局常量的赋值为字面量或常量,不涉及到方法和构造器的调用,则是链接阶段的准备环节;否则是初始化阶段赋值。 

public class TestM

{

    public static int a = 1;//初始化阶段

    public static final int INT_CONSTANT = 10;//链接阶段

    public static Integer INTEGER_CONSTANT1 = Integer.valueOf(100);//初始化阶段

    public static final Integer INTEGER_CONSTANT2 = Integer.valueOf(1000);//初始化阶段

    public static final String s0 = "hello";//链接阶段

    public static final String s1 = new String("hello");//初始化阶段

    public static String  s2 = "hello";//初始化阶段

    public static final int NUM = new Random().nextInt(10);//初始化阶段

    static int a = 10; //初始化阶段

    static final  int b = a ;//初始化阶段

    //static+final修饰的成员变量,为全局常量;给全局常量的赋值为字面量或常量,不涉及到方法和构造器的调用,

    // 则是链接阶段的准备环节;否则是初始化阶段赋值。

}

三 类的加载过程

3.1 概述

按照Java虚拟机规范,从class文件到加载到内存中的类,到类卸载出内存为止,它的整个生命周期包括如下7个阶段:在Java中数据类型分为基本数据类型和引用数据类型。基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载。

3.2 加载具体阶段*

1加载:

所谓装载,简而言之就是将Java类的字节码文件加载到机器内存中,并在内存中构建出Java类的原型——类模板对象。

2.链接:

1)验证:当类加载到系统后,就开始链接操作,验证是链接操作的第一步。它的目的是保证加载的字节码是合法、合理并符合规范的。验证的内容则涵盖了类数据信息的格式验证、语义检查、字节码验证,以及符号引用验证等。

2)准备:

简言之,为类的静态变量分配内存,并将其初始化为默认值

在这个阶段,虚拟机就会为这个类分配相应的内存空间,并设置默认初始值。

注意:Java并不支持boolean类型,对于boolean类型,内部实现是int,由于int的默认值是0,故对应的boolean的默认值就是false。

3)解析:

将类、接口、字段和方法的符号引用转为直接引用;也就是得到类、字段、方法在内存中的指针或者偏移量。

3.初始化执行类变量赋值和静态代码块

又父及子,静态先行。在加载一个类之前,虚拟机总是会试图加载该类的父类,因此父类的<clinit>总是在子类<clinit>之前被调用。也就是说,父类的static块优先级高于子类。 

4.使用阶段:

任何一个类型在使用之前都必须经历过完整的加载、链接和初始化3个类加载步骤。一旦一个类型成功经历过这3个步骤之后,开发人员可以在程序中访问和调用它的静态类成员信息(比如:静态字段、静态方法),或者使用new关键字为其创建对象实例。

5.卸载

当对象不再被使用时,java虚拟机的垃圾收集器将会回收堆中的对象,方法区中不再被使用的Class也要被卸载,否则方法区(Sun HotSpot永久代)会内存溢出。

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

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

相关文章

逻辑代数的基本规则

目录 逻辑代数的基本规则 带入规则 反演规则 对偶规则 逻辑代数的基本规则 带入规则 将逻辑等式两边的某一变量均用同一个逻辑函数代替&#xff0c;等式仍然成立。 可以用A非代替A&#xff0c;也可以用C代替B。 也可使用BC这样一个整体代替B。 反演规则 可以把与换或&#x…

Mysql高级教程

1.安装部署 安装依赖性&#xff1a; [rootmysql-node10 ~]# dnf install cmake gcc-c openssl-devel ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el7_4.x86_64.rpm rpcgen.x86_64 下载并解压源码包 [rootmysql-node10 ~]# tar zxf mysql-boost-5.7.44.tar.gz [rootmysql-no…

Java项目——苍穹外卖(一)

Entity、DTO、VO Entity&#xff08;实体&#xff09; Entity 是表示数据库表的对象&#xff0c;通常对应数据库中的一行数据。它通常包含与数据库表对应的字段&#xff0c;并可能包含一些业务逻辑。 DTO&#xff08;数据传输对象&#xff09; 作用&#xff1a;DTO 是用于在…

AutosarMCAL开发——基于EB Gpt驱动

目录 1.Gpt原理2.EB配置以及接口应用2.1 EB配置2.2 接口应用 3.总结 1.Gpt原理 autosar GPT模块&#xff08;General Purpose Timer&#xff0c;通用定时器&#xff09;主要用于汽车ECU中的时间测量、计数和产生定时中断。它支持单次性和周期性定时器&#xff0c;可以在达到预…

Bitvise——进入服务器的快捷方式

第一步&#xff1a;在连接进服务器后&#xff0c;点击左侧的保存配置文件&#xff0c;保存至桌面。 第二步&#xff1a;将保存的配置文件&#xff08;后缀为 .tlp&#xff09;打开方式改为bitvise。 第三步&#xff1a;双击配置文件&#xff08;后缀为 .tlp&#xff09;&#…

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理&#xff0c;在有一定基础认识的前提下&#xff0c;通过阅读kubelet源码&#xff0c;对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管…

Android终端如何快速接入GB28181平台实现实时音视频回传

技术背景 GB28181是由中国国家标准委员会发布的基于IP网络的安防视频监控标准。Android平台GB28181设备对接模块&#xff0c;主要涉及到视频监控领域&#xff0c;可实现不具备国标音视频能力的 Android终端&#xff0c;通过平台注册接入到现有的GB/T28181—2016服务&#xff0…

Ifream实现微前端效果

记得有人曾问过我&#xff0c;老旧的项目内容很多&#xff0c;项目卡&#xff0c;想要改造成类似微前端&#xff0c;领导想要快速&#xff0c;又不想系统重构、而且是不同子系统的协同&#xff0c;要怎么做&#xff1f;对方不想做太大的改造&#xff0c;所以想用ifream的方式动…

如何打造高效办公楼物业管理系统?Java SpringBoot+Vue架构详解,实现智能化管理,提升工作效率

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

【全网最全】2024年数学建模国赛A题30页完整建模文档+17页成品论文+保奖matla代码+可视化图表等(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片那是获取资料的入口&#xff01; 【全网最全】2024年数学建模国赛A题30页完整建模文档17页成品论文保奖matla代码可视化图表等&#xff08;后续会更新&#xff09;「首先来看看目前已有的资料&#xff0…

Bat的退役前

我们很讨厌bat 语法这版的命令形式后缀尽管古老&#xff0c;可是在涉及细微VS 项目op 时候&#xff0c;它起到了不可忽视且非它不行的效应 我们不想替历史背上厚重的学习包袱&#xff0c;可是我们能忽视BAT 吗 如若进入到 无window时代&#xff0c;我们几乎得全然依仗BAT专家。…

Hiredis的使用

Hiredis的使用 &#x1f4f8;这里安利一个github仓库介绍 图片生成 Socialify 一键生成专业 GitHub 仓库简介图 一、Hiredis的安装与使用 1、下载hiredis软件包&#xff0c; https://github.com/redis/hiredis.git 或者使用git下载到本地 git clone https://github.com/redi…

一文说清什么是数据仓库

01 数据仓库的概念 数据仓库的概念可以追溯到20世纪80年代&#xff0c;当时IBM的研究人员开发出了“商业数据仓库”。本质上&#xff0c;数据仓库试图提供一种从操作型系统到决策支持环境的数据流架构模型。 目前对数据仓库&#xff08;Data Warehouse&#xff09;的标准定义&a…

51单片机-DS1302(RTC实时时钟芯片)

数据手册在主页资源免费贡献 开发板芯片数据手册 https://www.alipan.com/s/nnkdHhMGjrz 提取码: 95ik 点击链接保存&#xff0c;

算法分享——《双指针》

文章目录 ✅[《移动零》](https://leetcode.cn/problems/move-zeroes/)&#x1f339;题目描述&#xff1a;&#x1f697;代码实现&#xff1a;&#x1f634;代码解析&#xff1a; ✅[《复写零》](https://leetcode.cn/problems/duplicate-zeros/)&#x1f339;题目描述&#xf…

Grafana 可视化配置

Grafana 是什么 Grafana 是一个开源的可视化和监控工具&#xff0c;广泛用于查看和分析来自各种数据源的时间序列数据。它提供了一个灵活的仪表盘&#xff08;dashboard&#xff09;界面&#xff0c;用户可以通过它将数据源中的指标进行图表化展示和监控&#xff0c;帮助分析趋…

Linux概述、远程连接、常用命令

Linux介绍 Linux操作系统介绍 Linux操作系统的特点 开源免费安全稳定可移植性好 Linux可以安装在不同的设备上 高性能 Linux的使用领域 应用服务器数据库服务器网络服务器虚拟化云计算嵌入式领域个人PC移动手机 Linux文件系统和目录 /&#xff1a;根目录&#xff0c;唯一/h…

flinkcdc 问题记录篇章

startupOptions 讲解 startupOptions 有三个参数initial、earliest、latest initial&#xff1a;因为binlog中不一定包含所有的数据&#xff0c;那么需要全表扫描所有的表&#xff0c;形成快照。常用于历史数据 earliest&#xff1a;从最早的变更日志开始读取&#xff08;仅增…

linux下进行lvm分区及扩容

目录 LVM存储管理介绍 lvm磁盘扩容有两种方式 创建lvm磁盘 1. 首先先加入第一块儿新的磁盘 2. 对新磁盘 /dev/sdb 进行分区 通过LVM命令创建新卷 1. 创建物理卷 2.创建卷组 并将物理卷加入其中 3. 创建逻辑卷并分配大小 4.格式化刚刚创建的硬盘 5. 挂载磁盘 扩容lvm…

第 2 章:AJAX 的使用

AJAX 的使用 核心对象&#xff1a;XMLHttpRequest&#xff0c;AJAX 的所有操作都是通过该对象进行的。 1. 使用步骤 创建 XMLHttpRequest 对象 var xhr new XMLHttpRequest(); 设置请求信息 xhr.open(method, url);//可以设置请求头&#xff0c;一般不设置 xhr.setReques…