JVM加载class文件的原理机制

1、JVM 简介

  JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后会写个复杂点class ,然后再找一些开源框架,比如Spring ,Hibernate 等等,再然后就开发企业级的应用,比如网站、企业内部应用、实时交易系统等等,直到某一天突然发现做的系统咋就这么慢呢,而且时不时还来个内存溢出什么的,今天是交易系统报了StackOverflowError ,明天是网站系统报了个OutOfMemoryError ,这种错误又很难重现,只有分析Javacore 和dump 文件,运气好点还能分析出个结果,运行遭的点,就直接去庙里烧香吧!每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子了。我想Java 做的久一点的都有这样的经历,那这些问题的最终根结是在哪呢?—— JVM 。

  JVM 全称是Java Virtual Machine ,Java 虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使用 VMWare不一样,那个虚拟的东西你是可以看到的,这个JVM 你是看不到的,它存在内存中。我们知道计算机的基本构成是:运算器、控制器、存储器、输入和输出设备,那这个JVM 也是有这成套的元素,运算器是当然是交给硬件CPU 还处理了,只是为了适应“一次编译,随处运行”的情况,需要做一个翻译动作,于是就用了JVM 自己的命令集,这与汇编的命令集有点类似,每一种汇编命令集针对一个系列的CPU ,比如8086 系列的汇编也是可以用在8088 上的,但是就不能跑在8051 上,而JVM 的命令集则是可以到处运行的,因为JVM 做了翻译,根据不同的CPU ,翻译成不同的机器语言。

  JVM 中我们最需要深入理解的就是它的存储部分,存储?硬盘?NO ,NO , JVM 是一个内存中的虚拟机,那它的存储就是内存了,我们写的所有类、常量、变量、方法都在内存中,这决定着我们程序运行的是否健壮、是否高效,接下来的部分就是重点介绍之。

回到顶部

2、JVM 的组成部分

我们先把JVM 这个虚拟机画出来,如下图所示:

 

从这个图中可以看到,JVM 是运行在操作系统之上的,它与硬件没有直接的交互。我们再来看下JVM 有哪些组成部分,如下图所示:

该图参考了网上广为流传的JVM 构成图,大家看这个图,整个JVM 分为四部分:

## Class Loader 类加载器 

类加载器的作用是加载类文件到内存,比如编写一个HelloWord.java 程序,然后通过javac 编译成class 文件,那怎么才能加载到内存中被执行呢?Class Loader 承担的就是这个责任,那不可能随便建立一个.class 文件就能被加载的,Class Loader 加载的class 文件是有格式要求,在《JVM Specification 》中式这样定义Class 文件的结构:

复制代码

  ClassFile {u4 magic;u2 minor_version;u2 major_version;u2 constant_pool_count;cp_info constant_pool[constant_pool_count-1];u2 access_flags;u2 this_class;u2 super_class;u2 interfaces_count;u2 interfaces[interfaces_count];u2 fields_count;field_info fields[fields_count];u2 methods_count;method_info methods[methods_count];u2 attributes_count;attribute_info attributes[attributes_count];}

复制代码

需要详细了解的话,可以仔细阅读《JVM Specification 》的第四章“The class File Format ”,这里不再详细说明。

友情提示:Class Loader 只管加载,只要符合文件结构就加载,至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。

## Execution Engine 执行引擎 

执行引擎也叫做解释器(Interpreter) ,负责解释命令,提交操作系统执行。

## Native Interface 本地接口

本地接口的作用是融合不同的编程语言为Java 所用,它的初衷是融合C/C++ 程序,Java 诞生的时候是C/C++ 横行的时候,要想立足,必须有一个聪明的、睿智的调用C/C++ 程序,于是就在内存中专门开辟了一块区域处理标记为native 的代码,它的具体做法是Native Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies 。目前该方法使用的是越来越少了,除非是与硬件有关的应用,比如通过Java 程序驱动打印机,或者Java 系统管理生产设备,在企业级应用中已经比较少见,因为现在的异构领域间的通信很发达,比如可以使用Socket 通信,也可以使用Web Service 等等,不多做介绍。

## Runtime data area 运行数据区 

运行数据区是整个JVM 的重点。我们所有写的程序都被加载到这里,之后才开始运行,Java 生态系统如此的繁荣,得益于该区域的优良自治。

整个JVM 框架由加载器加载文件,然后执行器在内存中处理数据,需要与异构系统交互是可以通过本地接口进行,瞧,一个完整的系统诞生了!

回到顶部

3、JVM加载class文件的原理机制 

   Java中的所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的,除非我们有特殊的用法,像是反射,就需要显式的加载所需要的类。

  类装载方式,有两种 
      1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中,
      2.显式装载, 通过class.forname()等方法,显式加载需要的类 
    隐式加载与显式加载的区别:两者本质是一样? 

     Java类的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到jvm中,至于其他类,则在需要的时候才加载。这当然就是为了节省内存开销。

   Java的类加载器有三个,对应Java的三种类:(java中的类大致分为三种:   1.系统类   2.扩展类 3.由程序员自定义的类 )

     Bootstrap Loader  // 负责加载系统类 (指的是内置类,像是String,对应于C#中的System类和C/C++标准库中的类)
            | 
          - - ExtClassLoader   // 负责加载扩展类(就是继承类和实现类)
                          | 
                      - - AppClassLoader   // 负责加载应用类(程序员自定义的类)

 三个加载器各自完成自己的工作,但它们是如何协调工作呢?哪一个类该由哪个类加载器完成呢?为了解决这个问题,Java采用了委托模型机制。

委托模型机制的工作原理很简单:当类加载器需要加载类的时候,先请示其Parent(即上一层加载器)在其搜索路径载入,如果找不到,才在自己的搜索路径搜索该类。这样的顺序其实就是加载器层次上自顶而下的搜索,因为加载器必须保证基础类的加载。之所以是这种机制,还有一个安全上的考虑:如果某人将一个恶意的基础类加载到jvm,委托模型机制会搜索其父类加载器,显然是不可能找到的,自然就不会将该类加载进来。

      我们可以通过这样的代码来获取类加载器:

ClassLoader loader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();

注意一个很重要的问题,就是Java在逻辑上并不存在BootstrapKLoader的实体!因为它是用C++编写的,所以打印其内容将会得到null。
      

前面是对类加载器的简单介绍,它的原理机制非常简单,就是下面几个步骤:

1.装载:查找和导入class文件;

2.连接:

      (1)检查:检查载入的class文件数据的正确性;

      (2)准备:为类的静态变量分配存储空间;

      (3)解析:将符号引用转换成直接引用(这一步是可选的)

3.初始化:初始化静态变量,静态代码块。

      这样的过程在程序调用类的静态成员的时候开始执行,所以静态方法main()才会成为一般程序的入口方法。类的构造器也会引发该动作。

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

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

相关文章

Unity添加所有场景到BuildSettings

Unity添加所有场景到BuildSettings using UnityEngine; using UnityEditor; using System.Collections.Generic; using System.IO; public class Tools : Editor {[MenuItem("Tools/添加所有场景到BuildSettings")]static void CheckSceneSetting(){List<string&…

C语言编译器(C语言编程软件)完全攻略(第三十部分:Xcode简明教程(使用Xcode编写C语言程序))

介绍常用C语言编译器的安装、配置和使用。 三十、Xcode简明教程&#xff08;使用Xcode编写C语言程序&#xff09; 在 Mac OS X 下学习C语言使用 Xcode。Xcode 是由Apple官方开发的IDE&#xff0c;支持C、C、Objective-C、Swift等&#xff0c;可以用来开发 Mac OS X 和 iOS 上…

Idea连接Docker在本地(Windows)开发SpringBoot

文章目录 1. 新建运行配置2. 修改运行目标3. 设置新目标Docker4. 选择运行主类5. 运行 当一些需要的服务在docker容器中运行时&#xff0c;因为docker网络等种种原因&#xff0c;不得不把在idea开发的springboot项目放到docker容器中才能做测试或者运行。 1. 新建运行配置 2. …

CSS 实现两个圆圈重叠部分颜色不同

这是期望实现的效果&#xff0c;由图可知&#xff0c;圆圈底图透明度是0.4&#xff0c;左侧要求重叠部分透明度是0.7&#xff0c;所以不能通过简单的透明度叠加来实现最右侧的效果。 这就需要另外新建一个图层来叠加在两个圆圈重叠上方。 直接看代码 .circle_hight {width: 1…

【数据库原理】(10)数据定义功能

SQL 数据定义功能包括定义模式、定义表、定义索引和定义视图,其语句如表所示。 一.创建、删除模式 1.创建模式 (Create Schema) 用途&#xff1a;创建模式是为了在数据库中定义一个新的命名空间&#xff0c;它可以包含多个数据库对象。 语法&#xff1a; CREATE SCHEMA &…

leetcode:908. 最小差值 I

一、题目 二、函数原型 int smallestRangeI(int* nums, int numsSize, int k) 三、思路 本题题目有些绕口&#xff0c;但是无伤大雅。本质就是可以对数组中的每个元素进行加/减 k 的操作&#xff0c;然后求数组中的最大、最小元素的最小差值。 分为几种情况&#xff1a; …

SwiftUI之深入解析如何使用accessibilityChartDescriptor视图修饰符为视图构建音频图表

一、DataPoint 结构体 在 SwiftUI 中构建一个简单的条形图视图开始&#xff0c;该视图使用垂直条形显示一组数据点。如下所示&#xff0c;有一个 DataPoint 结构&#xff0c;用于描述条形图视图中的条形&#xff0c;它具有 id、标签、数值和填充颜色&#xff1a; struct Data…

Notepad++ v7.7.1 安装及添加插件

1、notepad_v7.7.1.zip npp.7.7.1.Installer.x64.exe npp.7.7.1.Installer.x86.exe notepad_v7.7.1.ziphttps://www.123pan.com/s/VTMXjv-X6H6v.html 2、notepad插件包_64bit_4.zip ComparePlugin ---->文件对比插件 ComparePlugin.dllNppFTP ---->FTP、FTPES和SFTP …

Mac上安装 Node.js 的版本管理工具 n,以及 n 使用,的使用

安装 最近刚更换 Mac 本进行项目的开发&#xff0c;刚上手 Mac 本还不是很熟练&#xff0c;需要安装 Node.js 的包管理工具 在 Windows 上我是实用的 nvm 来管理的 Node 版本&#xff0c;但是我尝试下载 Nvm &#xff0c;发现下载安装后的 Nvm 无法使用&#xff0c;提示 “Th…

HDU - 2063 过山车(Java JS Python C)

题目来源 Problem - 2063 (hdu.edu.cn) 题目描述 RPG girls今天和大家一起去游乐场玩&#xff0c;终于可以坐上梦寐以求的过山车了。 可是&#xff0c;过山车的每一排只有两个座位&#xff0c;而且还有条不成文的规矩&#xff0c;就是每个女生必须找个男生做partner和她同坐…

git打tag以及拉取tag

场景&#xff1a;某次git代码发布后定版记录&#xff0c;将发版所在的commit时候代码打上tag记录&#xff0c;方便后期切换到对应tag代码位置。 查看所有tag名 git tag// 1.1.0 // 1.0.0查看tag和描述 git tag -l -n//1.0.0 云监管一期项目完结 //1.1.0 …

c语言-指针练习题

目录 前言一、题目一二、题目二总结 前言 为了巩固c语言中关于指针知识点的掌握&#xff0c;本篇文章记录关于指针的练习题。 一、题目一 有n个整数&#xff0c;使前面各数顺序往后移动m个位置&#xff0c;最后m个数变成最前面的m个数 写一函数实现以上功能&#xff0c;在主函…