类的加载

合集下载

类加载的三种方式

类加载的三种方式

类加载的三种⽅式类加载分为动态加载和静态加载。

动态加载是从外存储器中加载类,⼀般类加载机制分析的也是动态加载。

⽽静态加载本质上是从内存中创建类的实例对象,此时类已经被加载到内存中。

⼀.静态加载通过new关键字来创建Test的实例对象。

⼆.动态加载1.通过Class.forName()来加载类,然后调⽤类的newInstance()⽅法实例化对象。

2.通过类加载器的loadClass()⽅法来加载类,然后调⽤类的newInstance()⽅法实例化对象。

这⾥有⼏个需要⽐较的地⽅:1.通过new关键字实例化类的对象和通过Class.forName()加载类是当前类加载器,即this.getClass.getClassLoader,只能在当前类路径或者导⼊的类路径下寻找类。

⽽⽤指定的classLoader来加载类可以从当前路径外寻找类,这⾥的classLoader甚⾄可以⽤户⾃定义。

2.我们知道类加载机制的三个过程主要是加载-->连接-->初始化。

Class.forName()实际调⽤的是Class.forName(className,true,this.getClass.getClassLoader),第⼆个参数表⽰加载完后是否⽴即初始化,第三个参数即前⽂提到的表⽰是当前类加载器。

classLoader.loadClass()实际调⽤的是classLoader.loadClass(className,false),第⼆个参数表⽰加载完成后是否连接,即⽤此⽅法加载类,加载完成后不会去初始化,⽽⽤Class.forName()加载类加载完成后可以被初始化。

所以有些类如果加载完成后需要⽴即被初始化则必须使⽤Class.forName()。

例如在加载数据库驱动时,⼀般⽤Class.forName("com.mysql.jdbc.Driver")。

这是因为该驱动有⼀个在静态代码块中注册驱动的过程,所以需要被初始化。

java 类里的loadclass用法

java 类里的loadclass用法

java 类里的loadclass用法Java中的loadClass()方法是在Class类中定义的一个方法,用于动态加载类。

在程序运行时可以根据类的全限定名来加载指定的类文件,并返回对应的Class对象。

loadClass()方法的语法如下:`public Class<?> loadClass(String name) throws ClassNotFoundException`这个方法可以在当前的ClassLoader中通过类的全限定名来加载指定的类文件。

如果找不到该类文件,则会抛出ClassNotFoundException异常。

下面将详细介绍loadClass()方法的使用以及相关概念和实例。

1. 理解Java类加载器在介绍loadClass()方法之前,先来了解一下Java类加载器。

类加载器是Java虚拟机(JVM)的一个组件,用于从文件系统、网络或其他来源加载Java类文件。

Java虚拟机通过类加载器来定位并加载类文件,将其转换为一个Class对象,并存放在方法区(即运行时数据区域之一)。

一个Java类加载器通常是由一个ClassLoader类的实例来表示的。

Java 提供了三种内置的ClassLoader:- Bootstrap ClassLoader:负责加载Java核心类库,是虚拟机的一部分,无法直接获取。

- Extension ClassLoader:负责加载Java扩展库,如javax包下的类。

- System ClassLoader:也称为Application ClassLoader,负责加载应用程序的类,可以通过ClassLoader.getSystemClassLoader()来获取。

2. 使用loadClass()方法动态加载类loadClass()方法是ClassLoader类的一个原生方法,可以通过子类来调用。

在调用loadClass()方法时,会按照ClassLoader的委派模型进行类的加载。

classloader加载原理

classloader加载原理

classloader加载原理classloader是java中一个比较重要的类加载器,每一个程序和类都会存在一个classloader,classloader有三种主要的工作:加载类的二进制字节流、连接、初始化。

一、Classloader加载机制1、首先classloader会按照特定的方式去搜索类文件,当它找到了相应的类文件之后,它会将这个类文件转换成为二进制字节流,这里涉及到编译程序,classloader会使用编译程序将源程序编译成可执行文件。

2、接下来classloader会将这些二进制字节流存储在内存中,然后classloader会连接这些字节流,这一步是它将这些字节流组装成一个完整的类文件,这里涉及到类的加载,这些加载的类可以被访问,但是它们的代码还未被执行。

3、最后classloader会初始化这些加载的类,这一步就是它将这些类的代码执行,这里classloader会执行所有类变量的初始化,同时也会执行所有静态代码块的内容,最后我们就可以得到一个完整的类文件。

二、Classloader的三种类型1、Bootstrap Classloader:它是用来加载JRE的核心类的,它的实现是C++语言,它的加载范围是从<JAVA_HOME>lib下面开始,这个类加载器不需要程序员编写任何外部类。

2、Extension Classloader:它是用来加载扩展类的,从<JAVA_HOME>libext开始加载,它继承自Bootstrap Classloader,这种类加载器也不需要程序员手动编写任何外部类。

3、Application Classloader:它是用来加载程序类的,它继承自Extension Classloader,它从ClassPath(来自系统变量或者命令行参数)所指定的路径中加载类,但是它不会加载扩展类。

三、Classloader安全机制1、安全性验证:Classloader在加载类的时候会先验证这个类文件,检查它是否符合class文件格式,其次classloader会过滤掉由它本身加载的不安全的类,这涉及到安全管理器的配置,例如:可以设置它只能加载特定的域名下的类文件。

jvm 打印类加载 参数

jvm 打印类加载 参数

jvm 打印类加载参数JVM(Java虚拟机)是Java程序的运行环境,它扮演着将Java字节码转换为机器码并执行的关键角色。

在Java应用程序启动时,JVM会负责加载类并执行相应的操作。

本文将深入探讨JVM的类加载过程,并分析其中的参数。

一、类加载概述在Java中,类是代码的基本组织单元,它被封装在Java源文件中,并经过编译为字节码文件(.class)。

类加载是将字节码文件加载到JVM中并转换为可执行代码的过程。

JVM的类加载机制具有懒加载的特点,即在需要使用某个类时才会加载它。

二、类加载过程1.加载(Loading):将字节码文件加载到JVM中,它可以通过文件系统、网络等方式获取字节码文件。

加载后的类会被存放在方法区(Method Area)中,并被分配一个唯一的类加载器实例。

2.链接(Linking):链接分为三个阶段,包括验证(Verification)、准备(Preparation)和解析(Resolution)。

- 验证:确保字节码文件符合JVM规范,不包含安全漏洞。

- 准备:为类的静态变量分配内存,并设置默认初值。

- 解析:将符号引用转换为直接引用,以便JVM能够快速访问到类、方法和字段。

3.初始化(Initialization):执行类的初始化代码,包括静态变量赋值和静态块的执行。

初始化是类加载过程中的最后一步,只有当类被使用时才会触发。

三、类加载参数1.-verbose:class该参数用于打印类加载的详细信息,包括类的加载、链接和初始化过程。

通过查看该输出信息,可以了解到类加载器的工作情况,以及类加载的顺序和时间等。

2.-Xbootclasspath/a:path该参数用于指定引导类加载器搜索类的路径。

在Java应用程序启动时,引导类加载器会先搜索这个路径下的类,如果找到了对应的类,则直接加载,不再使用默认的搜索路径。

这个参数可以用来加载自定义的类或者覆盖JDK中的类。

3.-Xms<size>和-Xmx<size>这两个参数用于指定JVM的初始堆大小和最大堆大小。

Java 类加载原理解析

Java 类加载原理解析

Java类加载原理解析分类:java应用2010-07-14 14:07 55人阅读评论(0) 收藏举报Java类加载原理解析1基本信息摘要:每个java开发人员对ng.ClassNotFoundExcetpion这个异常肯定都不陌生,这背后就涉及到了java 技术体系中的类加载。

Java的类加载机制是java技术体系中比较核心的部分,虽然和大部分开发人员直接打交道不多,但是对其背后的机理有一定理解有助于排查程序中出现的类加载失败等技术问题,对理解java虚拟机的连接模型和java语言的动态性都有很大帮助。

由于关于java类加载的内容较多,所以打算分三篇文章简述一下:第一篇:java类加载原理解析第二篇:插件环境下类加载原理解析第三篇:线程上下文类加载器分类:开发技术->J2EE标签:Java类加载类加载器双亲委派机制自定义类加载器作者:朱兴创建于2007-6-22MSN:zhu_xing@2Java虚拟机类加载器结构简述2.1JVM三种预定义类型类加载器我们首先看一下JVM预定义的三种类型类加载器,当一个JVM 启动的时候,Java 缺省开始使用如下三种类型类装入器:启动(Bootstrap)类加载器:引导类装入器是用本地代码实现的类装入器,它负责将<Java_Runtime_Home>/lib 下面的类库加载到内存中。

由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。

标准扩展(Extension)类加载器:扩展类加载器是由Sun 的ExtClassLoader(uncher$ExtClassLoader)实现的。

它负责将< Java_Runtime_Home >/lib/ext 或者由系统变量java.ext.dir 指定位置中的类库加载到内存中。

开发者可以直接使用标准扩展类加载器。

系统(System)类加载器:系统类加载器是由Sun 的AppClassLoader(uncher$AppClassLoader)实现的。

类加载的过程及各部件存放的位置

类加载的过程及各部件存放的位置
{
=name;
}
public void speak()
{
System.out.println(+"..."+this.age);
}
public static void showCountry()
{
System.out.println("country="+country);
p.setName("lisi");
p.speak();
Person.showCountry();
}
static
{
System.out.println("StaticDemo 静态代码块2");
}
}
输出结果:
StaticDemo 静态代码块1
StaticDemo 静态代码块2
静态代码块被执行
null...0 //构造代码块
lisi...100 //speak()
country=cn //showCountry()
Person(String name,int age)
{
=name;
this.age=age;
}
static
{
System.out.println("静态代码块被执行");
}
{ System.out.println(name+"..."+age);
}
public void setName(String name)
3.将"lisi" 赋值给临时变量name。

java类加载方法

java类加载方法

java类加载方法
Java类加载是指将Java字节码文件加载到Java虚拟机中,并将其转换为可执行的Java类的过程。

Java类加载器是用于动态加载Java类的一种机制。

Java类加载器负责查找Java类并加载它们。

Java类加载器有三种类型:启动类加载器、扩展类加载器和应用程序类加载器。

启动类加载器负责加载Java类库,扩展类加载器负责加载扩展库,而应用程序类加载器则加载应用程序中的类。

类加载过程包括加载、验证、准备和解析阶段。

加载阶段负责查找和加载类的字节码,验证阶段则验证类的字节码是否合法,准备阶段则为类的静态变量分配空间并初始化,而解析阶段则处理类之间的引用关系。

Java还支持动态类加载,这是一种在运行时加载类的机制。

动态类加载允许在程序运行时根据需要动态加载类,这有助于提高程序的灵活性和可扩展性。

动态类加载通常使用反射机制来实现。

- 1 -。

WebLogic类加载过程简述

WebLogic类加载过程简述

WebLogic类加载过程王明杰20061012 19:28-21:59英文水平有限,翻译的肯定有不对的地方,欢迎指正。

希望能够各位同事在使用weblogic的过程中带来帮助。

小注:2006-10-12 下午,在weblogic中部署一个启动类,部署了近2个小时,weblogic总是提示“找不到类的异常”。

心情很是郁闷。

“大事问老婆,小事问goole”,一个字“搜”。

终于找到了WebLogic的官方文档,摘录下来,进行了翻译,终于对WebLogic的类的加载过程有了比较系统的了解。

希望该文档能够帮助和我有同样疑惑的人走出困境,共同进步!!!V ersion 0.1msn:wangmingjie_2002@官方原版(19:30开始)20061012开始WebLogic Server Application ClassloadingThe following sections provide an overview of Java classloaders, followed by details about WebLogic Server J2EE application classloading.下面的部分概况的介绍了java的类装载器,接着详细的介绍了WebLogicJ2EE应用服务器(WebLogic Server J2EE application )的类装载过程。

▪Java Classloader Overview java类转载器综述▪WebLogic Server Application Classloader Overview WebLogic 应用服务器类装载器介绍。

▪Resolving Class References Between Modules and ApplicationsJava Classloader OverviewClassloaders are a fundamental module of the Java language. A classloader is a part of the Java virtual machine (JVM) that loads classes into memory;a classloader is responsible for finding and loading class files at run time. Every successful Java programmer needs to understand classloaders and their behavior. This section provides an overview of Java classloaders.类装载器是java语言的一个基本模块,类装载器是java虚拟机的一部分,把相应的类装载到内存中,类装载器负责在运行期间找到类并载入类。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

类从加载到虚拟机到卸载,它的整个生命周期包括:加载(Loading),验证(Validation),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)。

其中,验证、准备和解析部分被称为连接(Linking)。

加载:在加载阶段,虚拟机主要完成三件事:1.通过一个类的全限定名来获取定义此类的二进制字节流。

2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。

3.在Java堆中生成一个代表这个类的ng.Class对象,作为方法区域数据的访问入口。

验证:验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。

如果验证失败,就会抛出一个ng.VerifyError异常或其子类异常。

验证过程分为四个阶段:1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。

2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。

3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。

4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。

准备:准备阶段为变量分配内存并设置类变量的初始化。

在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量。

对已非final的变量,JVM会将其设置成“零值”,而不是其赋值语句的值:pirvate static int size = 12;那么在这个阶段,size的值为0,而不是12。

final修饰的类变量将会赋值成真实的值。

解析:解析过程是将常量池内的符号引用替换成直接引用。

主要包括四种类型引用的解析。

类或接口的解析、字段解析、方法解析、接口方法解析。

初始化:在准备阶段,类变量已经经过一次初始化了,在这个阶段,则是根据程序员通过程序制定的计划去初始化类的变量和其他资源。

这些资源有static{}块,构造函数,父类的初始化等。

至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。

都是父类先执行<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)再执行构造方法虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。

Java语言里,类型的加载和连接过程是在程序运行期间完成的。

类的生命周期:加载loading验证verification准备preparation解析resolution初始化initialization使用using卸载unloading有且只有以下四种情况必须立即对类进行”初始化”(称为对一个类进行主动引用):1.遇到new、getstatic、putstatic、invokestatic这四条字节码指令时(使用new实例化对象的时候、读取或设置一个类的静态字段、调用一个类的静态方法)。

2.使用ng.reflet包的方法对类进行反射调用的时候。

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

4.当虚拟机启动时,虚拟机会初始化主类(包含main方法的那个类)。

被动引用:1.通过子类引用父类的静态字段,不会导致子类初始化(对于静态字段,只有直接定义这个字段的类才会被初始化)。

2.通过数组定义类应用类:ClassA [] array=new ClassA[10]。

触发了一个名为[LClassA的类的初始化,它是一个由虚拟机自动生成的、直接继承于Object的类,创建动作由字节码指令newarray触发。

3.常量会在编译阶段存入调用类的常量池。

编译器会为接口生成<clinit>()构造器,用于初始化接口中定义的成员变量。

一个接口在初始化时,并不要求其父类接口全部完成了初始化,只有在真正使用到父接口的时候才会初始化。

1. 加载1.通过一个类的全限定名来获取此类的二进制字节流。

2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。

3.在java堆中生成一个代表这个类的Class对象,作为方法区这些数据的访问入口。

2. 验证验证:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

虚拟机规范:如果验证到输入的字节流不符合Class文件的存储格式,就抛出一个ng.VerifyError异常或其子类异常。

1.文件格式验证:验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。

这个阶段的验证时给予字节流进行的,经过了这个阶段的验证之后,字节流才会进入内存的方法区中进行存储所以后面的验证阶段都是给予方法区的存储结构进行的。

2.元数据验证:对类的元数据信息进行语义校验,保证不存在不符合java语言规范的元数据信息。

3.字节码验证:进行数据流和控制流分析,对类的方法体进行校验分析,保证被校验的类的方法在运行时不会做出危害虚拟机安全的行为。

4.符号引用验证:发生在虚拟机将符号引用转化为直接引用的时候(解析阶段),对常量池中的各种符号引用的信息进行匹配性的校验。

3. 准备准备阶段是正式为类变量分配内存并设置类变量初始值(各数据类型的零值)的阶段,这些内存将在方法区中进行分配。

但是如果类字段的字段属性表中存在ConstantValue属性,那在准备阶段变量值就会初始化为ConstantValue属性指定的值。

public static final int value=122;4. 解析解析阶段是在虚拟机将常量池内的符号引用替换为直接引用的过程。

符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。

符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。

直接引用:直接引用可以是直接指向目标的指针、相对偏移量或者一个能间接定位到目标的句柄。

如果有了直接引用,那引用的目标必定已经在内存中存在。

A. 类或接口(对应于常量池的CONSTANT_Class_info类型)的解析:假设当前代码所处的类为D,需要将一个从未解析过的符号引用N解析为一个类或接口C的直接引用:1.如果C不是一个数组类型,虚拟机将会把代表C的全限定名传递给D的类加载器去加载这个类。

2.如果C是一个数组类型,并且数组的元素类型为对象(N的描述符类似[ng.Integer),将会加载数组元素类型(ng.Integer),接着由虚拟机生成一个代表此数组维度和元素的数组对象。

3.如果以上过程没有发生异常,则C在虚拟机中已经成为了一个有效的类和接口了,之后还要进行的是符号引用验证,确认D是否具有对C的访问权限,如果没有,将抛出ng.IllegalAccessError异常。

B. 字段(对应于常量池的CONSTANT_Fieldref_info类型)解析:1.对字段表中的class_index项中索引的CONSTANT_Class_info符号引用进行解析。

用C表示这个字段所属的类或接口。

2.如果C本身就包含了简单名称和字段描述符都与目标相匹配的字段,则返回这个字段的直接引用。

3.否则,如果C实现了接口,则会按照继承关系从下往上递归搜索各个接口和他的父接口,如果接口中包含了简单名称和字段描述符都与目标相匹配的字段,则返回这个字段的直接引用。

4.否则,如果C不是ng.Object类型的话,将会按照继承关系从下往上递归的搜索其父类,如果在父类中包含了简单名称和字段描述符都与目标相匹配的字段,则返回这个字段的直接引用。

5.否则,查找失败,抛出ng.NoSuchFieldError异常。

虚拟机的编译器实现可能会更严格:如果一个同名字段同时出现在C实现的接口和父类中,或者同时在自己或父类的多个接口中出现,编译器将可能拒绝编译。

C. 类方法(对应于常量池的CONSTANT_Methodref_info类型)解析:1.对方法表中的class_index项中索引的CONSTANT_Class_info符号引用进行解析。

用C表示这个方法所属的类或接口。

2.类方法和接口方法符号引用的常量类型定义是分开的,如果在类方法表中发现class_index中索引的C是个接口,则抛出ng.IncompatibleClassChangeError。

3.在类C中查找是否有简单名称和描述符都与目标相匹配的方法,如果有则返回这个方法的直接引用。

4.否则,在C的父类中递归查找是否有简单名称和描述符都与目标相匹配的方法,如果有则返回这个方法的直接引用。

5.否则,在C实现的接口列表及它们的父接口中递归的查找是否有简单名称和描述符都与目标相匹配的方法,如果有说明C是个抽象类,查找结束,抛出ng.AbstractMethodError 异常。

6.否则,查找失败,抛出ng.NoSuchMethodError异常。

7.如果查找返回了直接引用,将会对这个方法进行权限验证,如果发现不具备对这个方法的访问权限,则抛出ng.IllegalAccessError异常。

D. 接口方法(对应于常量池的CONSTANT_InterfaceMethodref_info类型):1.对方法表中的class_index项中索引的CONSTANT_Class_info符号引用进行解析。

用C表示这个方法所属的类或接口。

2.如果在接口方法表中发现class_index中索引的C是个类,则抛出ng.IncompatibleClassChangeError。

3.否则,在接口C中查找是否有简单名称和描述符都与目标相匹配的方法,如果有则返回这个方法的直接引用。

4.否则,在接口C的父接口中递归查找,知道ng.Object类(包括在内),看是否有简单名称和描述符都与目标相匹配的方法,如果有则返回这个方法的直接引用。

5.否则,查找失败,抛出ng.NoSuchMethodError。

5. 初始化初始化阶段是执行类构造器<clinit>()方法的过程。

1.<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定的。

静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块中可以赋值,但是不能访问。

2. 方法与实例构造器<init>()不同,不需要显示的调用父类构造器,虚拟机会保证在子类的<clinit>()方法执行之前,父类的<clinit>()已经执行完毕。

相关文档
最新文档