VM 加载class文件的原理是什么?

2021-04-28 20:03发布

6条回答
tiu
1楼 · 2021-04-30 16:52.采纳回答

1. Java中的所有类,必须被装载到JVM中才能运行,这个装载工作是由JVM中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,作用就是在运行时加载类。

Java类加载器基于三个机制:委托、可见性和单一性。

(1)委托机制是指加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或加载这个类,那么再加载它。

(2)可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。

(3)单一性原理是指一个类仅被加载一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。

2. Java中的类大致分为三种:

(1)系统类

(2)扩展类

(3)由程序员自定义的类

3. 类装载有两种方式

(1)隐式装载:

程序在运行过程中当碰到通过new等方式生成类或者子类对象、使用类或者子类的静态域时,隐式调用类加载器加载对应的的类到JVM中。

(2)显式装载:

通过调用Class.forName()或者ClassLoader.loadClass(className)等方法,显式加载需要的类。

4. 类加载的动态性体现

一个应用程序总是由n多个类组成,Java程序启动时,并不是一次把所有的类全部加载再运行,他总是把保证程序运行的基础类一次性加载到JVM中,其他类等到JVM用到的时候再加载,这样是为了节省内存的开销,因为Java最早就是为嵌入式系统而设计的,内存宝贵,而用到时再加载这也是Java动态性的一种体现。

5. Java类加载器

Java中的类加载器实质上也是也是类,功能是把类加载入JVM中,值得注意的是JVM的类加载器有三个,原因有:一方面是为了分工明确,各自负责各自的区块,另一方面为了实现委托模型。

层次结构如下:

BootStrap Loader(引导类加载器) ----- 负责加载系统类


ExtClassLoader(扩展类加载器) ----- 负责加载扩展类

AppClassLoade(应用类加载器)r ----- 负责加载应用类

6. 类加载器之间如何协调工作的

Java中有三个类加载器,碰到一个类需要加载时,Java采用委托模型机制来协调和区分该由哪个类加载器完成。简单来说就是,“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入”,如果Parent找不到,那么才由自己依照自己的搜索路径搜索类。


Java语言是一种具有动态性的解释型语言,类(class)只有被加载到JVM中后才能运行。当运行指定程序时,JVM会将编译生成的.class文件按照需求和一定的规则加载到内存中,并组织成为一个完整的Java应用程序。这个加载过程是由类加载器来完成的,具体来说,就是由ClassLoader和它的子类来实现的。类加载器本身也是一个类,其实质是把类文件从硬盘读取到内存中。

类的加载方式分为隐式加载与显式加载两种。隐式加载指的是程序在使用new等方法创建对象时,会隐式地调用类的加载器把对应的类加载到JVM中。显式加载指的是通过直接调用class.forName()方法来把所需要的类加载到JVM中。

任何一个工程项目都是由许多个类组成的,当程序启动时,只把需要加载的类加载到JVM中,其他类只有被使用到的时候才会被加载,采用这种方法,一方面可以加快加载速度,另外一方面可以节约程序运行过程中对内存的开销。此外,在Java语言中,每个类或接口都对应一个.class文件,这些文件可以被看成一个个可以被动态加载的单元,因此当只有部分类被修改时,只需要重新编译变化的类即可,而不需要重新编译所有文件,因此加快了编译速度。


JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。  由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。  类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:  Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);  Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;  System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。

py大白
4楼 · 2021-05-16 15:03

VM 加载class文件的原理是什么?Java类加载器基于三个机制:委托、可见性和单一性。

(1)委托机制是指加载一个类的请求交给父类加载器,如果这个父类加载器不能够找到或加载这个类,那么再加载它。

(2)可见性的原理是子类的加载器可以看见所有的父类加载器加载的类,而父类加载器看不到子类加载器加载的类。

(3)单一性原理是指一个类仅被加载一次,这是由委托机制确保子类加载器不会再次加载父类加载器加载过的类。

一. Java中的类大致分为三种:

(1)系统类

(2)扩展类

(3)由程序员自定义的类

二. 类装载有两种方式

(1)隐式装载:

程序在运行过程中当碰到通过new等方式生成类或者子类对象、使用类或者子类的静态域时,隐式调用类加载器加载对应的的类到JVM中。

(2)显式装载:

通过调用Class.forName()或者ClassLoader.loadClass(className)等方法,显式加载需要的类。


路小雨xiaoyu
5楼 · 2021-06-03 17:05

一、原理机制

  虚拟机(jvm)把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型。

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

类装载的方式,有两种:

1、隐式装载,程序在运行过程中当碰到通过new等方式生成对象时,隐式调用类装载器对应的类到jvm中

2、显示装载,通过class.forname()等方式,显示加载需要的类

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

二、类加载器

  JVM中类的加载是由有类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,他负责在运行时查找和装入类文件中的类。

2.1、什么是类加载器,类加载器有哪些

  实现通过类的全限定名获取该类的二进制字节流的代码块叫做类加载器,它把类的.class文件的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的class对象,加载完成后,Class对象还不完整,所以此时的类还不可用。

  主要有以下四种类加载器:

  1、启动类加载器(Bootstrap ClassLoader)用来加载java核心类库,无法被java程序直接引用。

  2、扩展类加载器(Extensions ClassLoader)用来加载java的扩展库。java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载java类,它的父类加载器是Bootrap。

  3、系统类加载器(System ClassLoader)根据java应用的类路径(CLASSPATH)来加载java类。一般来说,java应用的类都是由它来完成加载的。可以通过ClassLoader.getSystemLoader()来获取它,它是应用最广泛的类加载器。。

  4、用户自定义类加载器,通过继承java.lang.ClassLoader类的方式实现。

2.2类装载的执行过程

类装载分为以下5个步骤:

  • 加载:根据查找路径找到相应的class问价然后导入;

  • 验证:检查加载的class文件的正确性;

  • 准备:给类中的静态标量分配内存空间;

  • 解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;

  • 初始化:对静态变量和静态代码块进行初始化工作;

三、双亲委派模型

  在介绍双亲委派模型之前回顾一下类加载器。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立在JVM中的唯一性,每个类加载器,都有一个独立的类名称空间。类加载器就是根据全限定名将class文件加载到JVM中,然后再转化为class对象。

 

 

 类加载器分类:

  • 启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分,用来加载Java_HOME/lib目录中的,或者被-Xbootclasspath参数所指定的路径中并且被虚拟机识别的类库;

  • 扩展类加载器(Extension ClassLoader),负责加载\lib\ext目录或Java.ext.dirs系统变量所指定的路径中的所有类库;

  • 应用程序类加载器(Application ClassLoader),负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况下,我们没有自定义类加载器,默认就是用这个加载器。

  从Java 2(JDK 1.2)开始,类加载过程采取了父亲委派机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootrap是根加载器,其他的加载器都有且仅有一个父类加载器。

  双亲委派模型:如果一个类加载器收到了类加载的请求,他首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到顶层的启动类加载器中,只有当父类加载器无法完成加载请求(它的搜素范围中没找到所需的类)时,子加载器才会尝试去加载类。

  采用双亲委派的一个好处是比如加载位于rt.jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层进行加载,这样就保证了使用不同的类加载器最终得到的都是一个Object对象。

  简述双亲委派:当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。

zgzbs
6楼 · 2021-08-26 17:55

在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备、解析
装载:查找和导入类或接口的二进制数据;
链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
校验:检查导入类或接口的二进制数据的正确性;
准备:给类的静态变量分配并初始化存储空间;
解析:将符号引用转成直接引用;
初始化:激活类的静态变量,初始化Java代码和静态Java代码块

相关问题推荐

  • 回答 22

    忙的时候项目期肯定要加班 但是每天加班应该还不至于

  • 回答 2

    Statement的execute(String query)方法用来执行任意的SQL查询,如果查询的结果是一个ResultSet,这个方法就返回true。如果结果不是ResultSet,比如insert或者update查询,它就会返回false。我们可以通过它的getResultSet方法来获取ResultSet,或者通过getUpda...

  • 回答 5
    已采纳

    工信部证书含金量较高。工信部是国务院的下属结构,具有发放资质、证书的资格。其所发放的证书具有较强的权威性,在全国范围内收到认可,含金量通常都比较高。 工信部证书,其含义也就是工信部颁发并承认的某项技能证书,是具有法律效力的,并且是国家认可的...

  • 回答 108
    已采纳

    虽然Java人才越来越多,但是人才缺口也是很大的,我国对JAVA工程师的需求是所有软件工程师当中需求大的,达到全部需求量的60%-70%,所以Java市场在短时间内不可能饱和。其次,Java市场不断变化,人才需求也会不断增加。马云说过,未来的制造业要的不是石油,...

  • 回答 16
    已采纳

    就是java的基础知识啊,比如Java 集合框架;Java 多线程;线程的五种状态;Java 虚拟机;MySQL (InnoDB);Spring 相关;计算机网络;MQ 消息队列诸如此类

  • 回答 70
    已采纳

    学Java好不好找工作?看学完Java后能做些什么吧。一、大数据技术Hadoop以及其他大数据处理技术都是用Java或者其他,例如Apache的基于Java 的 HBase和Accumulo以及ElasticSearchas。但是Java在此领域并未占太大空间,但只要Hadoop和ElasticSearchas能够成长壮...

  • 回答 12

    1)#{}是预编译处理,$ {}是字符串替换。2)MyBatis在处理#{}时,会将SQL中的#{}替换为?号,使用PreparedStatement的set方法来赋值;MyBatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。3)使用 #{} 可以有效的防止SQL注入,提高系统安全性。...

  • 回答 32

    只可以学习一些非常简单的基础概念,初中生如果不是非常有天赋,是很难听懂和学会的,当然如果非常喜欢的话,可以去研究它,当年爱因斯坦就是自己钻研,数学和音乐,加油你也可以的。...

  • 回答 4

    1、反射对单例模式的破坏采用反射的方式另辟蹊径实例了该类,导致程序中会存在不止一个实例。解决方案其思想就是采用一个全局变量,来标记是否已经实例化过了,如果已经实例化过了,第 二次实例化的时候,抛出异常2、clone()对单例模式的破坏当需要实现单例的...

  • 回答 5

     优点: 一、实例控制  单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。 二、灵活性  因为类控制了实例化过程,所以类可以灵活更改实例化过程。 缺点: 一、开销  虽然数量很少,但如果每次对象请求引用时都要...

  • 回答 4

    这个主要是看你数组的长度是多少, 比如之前写过的一个程序有个数组存的是各个客户端的ip地址:string clientIp[4]={XXX, xxx, xxx, xxx};这个时候如果想把hash值对应到上面四个地址的话,就应该对4取余,这个时候p就应该为4...

  • 回答 6

     哈希表的大小 · 关键字的分布情况 · 记录的查找频率 1.直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)。...

  • 回答 6

    哈希表的大小取决于一组质数,原因是在hash函数中,你要用这些质数来做模运算(%)。而分析发现,如果不是用质数来做模运算的话,很多生活中的数据分布,会集中在某些点上。所以这里最后采用了质数做模的除数。 因为用质数做了模的除数,自然存储空间的大小也用质数了...

  • 回答 2

    是啊,哈希函数的设计至关重要,好的哈希函数会尽可能地保证计算简单和散列地址分布均匀,但是,我们需要清楚的是,数组是一块连续的固定长度的内存空间

  • 回答 3

     解码查表优化算法,seo优化

  • 回答 5

    就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度...

没有解决我的问题,去提问