在java语言里,类型的加载、连接和初始化过程都是在程序运行期间完成的
加载:
- 通过类的全限定名来获取定义此类的二进制流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据的访问入口
上面第一点,有很大的灵活性,可以从ZIP包中读取,从网络中获取,运行时计算生成(动态代理proxy),由其他文件生成(jsp),从数据库读取....
加载完成后,虚拟机外部的二进制字节流就按照虚拟机所需要的格式存储在方法区之中。然后在内存中实例化一个java.lang.Class对象(并没有明确规定是在java堆中,对与HotsPot虚拟机而言,Class对象比较特殊,它虽然是对象,但是放在方法区里面),这个对象作为程序访问方法区中的这些类型数据的外部接口。
验证:
各种验证....
符号引用验证,对类自身以外(常量池中各种符号引用)的信息进行匹配性校验
符号引用中通过字符串描述的权限定名是否能找到对应的类....
准备:
正式为类变量分配内存并设置类变量初始值阶段,这些变量使用方法区内存。
解析:
将常量池中的符号引用替换为直接引用
初始化:
<clinit>()方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块(static{})中的语句合并产生的。虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确的加锁、同步。
类初始化条件:
- 使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候,以及调用这个类的静态方法。
- 使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化则需要先触发其初始化。
- 当初始化一个类的时候,发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
- 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法那个类),虚拟机会先初始化这个类
- 当使用1.7的动态语言支持,如果一个,,,,
以上5中情景称为对一个类的主动引用,除此之外,所有引用类的方式都不会触发初始化,成为被动引用。
例:
- 通过子类引用父类的静态字段,只会触发父类的初始化而不会触发子类的初始化。
- 通过数组定义来引用类,不会触发此类的初始化
- 常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类初始化。
类与加载器
对与任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在jvm中的唯一性。
比较两个类是否“相等”,只有在这个两个类是同一个类加载器加载的前提下才有意义。否则即使这两个类来源同一个Class文件,被同一个虚拟机加载,但是加载他们的加载器不同,那么这两个类必定不相等。
这里所指的相等,包括代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括使用instanceof关键字做对象所属关系判定等情况。
public class RunMain { public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { ClassLoader myLoader = new ClassLoader() { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { try { String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class"; InputStream in = getClass().getResourceAsStream(fileName); if (in == null) return super.loadClass(name); byte[] b = new byte[in.available()]; in.read(b); return defineClass(name, b, 0, b.length); } catch (IOException e) { throw new ClassNotFoundException(); } } }; Object obj = myLoader.loadClass("i.main.RunMain").newInstance(); System.out.println(obj.getClass());//class i.main.RunMain System.out.println(obj instanceof i.main.RunMain);//false } }
双亲委派模型
一种启动类加载器(Bootstrap ClassLoader)虚拟机实现的加载器
另一种java语言实现,独立于虚拟机外部,都继承自抽象类java.lang.ClassLoader
- 启动类加载器(Bootstrap ClassLoader):这个类加载器负责加载存放在<JAVA_HOME>\lib目录中的,启动类加载器无法被java程序直接引用,在自定义类加载器时,如果需要把加载请求委派给引导类加载器,直接使用null代替即可。
- 扩展类加载器(Extension ClassLoader):这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,可以直接使用扩展类加载器。
- 启用程序类加载器(Application ClassLoader):这个类由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般称为系统加载器。它负责加载用户类路径(ClassPath)上所制定的类库,可以直接使用这个类加载器,如果应用程序中没有自定义过的类加载器,一般情况下这个就是程序中默认的类加载器。
- 如果有必须要还可以加入自己定义的类加载器
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。
使用这种模型来组织类加载器之间的关系的好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如java.lang.Object类,无论哪个类加载器去加载该类,最终都是由启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。否则的话,如果不使用该模型的话,如果用户自定义一个java.lang.Object类且存放在classpath中,那么系统中将会出现多个Object类,应用程序也会变得很混乱。如果我们自定义一个rt.jar中已有类的同名Java类,会发现JVM可以正常编译,但该类永远无法被加载运行。
String str = a+b+c 编译成.class文件后,会通过StringBuilder优化
相关推荐
总结,JVM 类加载机制是Java平台的核心特性之一,它确保了程序的稳定运行和动态扩展能力。理解类加载器的工作原理和双亲委派模型对于优化程序性能、解决类冲突以及构建复杂的模块化系统至关重要。在实际开发中,掌握...
### JVM实战-JVM类加载机制案例分析 #### 实验背景与目标 本次实验的主要目的是深入理解Java虚拟机(JVM)中的类加载机制。通过实践操作,掌握类的加载、连接与初始化过程,了解不同类型的类加载器及其工作原理,...
Java虚拟机(JVM)是Java程序运行的基础,它的类加载机制是理解Java应用程序如何启动和执行的关键部分。本文将深入JDK源码,详细解析JVM类加载机制的各个环节,帮助开发者更好地理解和优化自己的代码。 类加载机制...
在Java开发中,JVM(Java虚拟机)的类加载机制是至关重要的,因为它负责将类的字节码转换为运行时的实例。本专题"性能调优专题-jvm类加载机制-performance-jvmclassloader"深入探讨了如何通过理解并优化类加载过程来...
Java虚拟机(JVM)的类加载机制是Java运行时环境的重要组成部分,它负责将类的字节码文件加载到内存中,进行一系列处理并使其成为可执行的Java类型。这个过程包括五个主要阶段:加载、验证、准备、解析和初始化。 1...
JVM的类加载机制是Java程序运行的基础,它包括加载、验证、准备、解析和初始化等阶段。通过理解类加载机制,我们可以更好地管理类的生命周期,实现动态加载和卸载类,以及优化程序的性能。随着Java技术的不断发展,...
锁以及jvm类加载机制
JVM的类加载机制是JVM的核心机制之一,它把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初识化,形成可以被虚拟机直接使用的Java类型。 Java代码执行流程是JVM的核心流程之一,它首先通过...
类缓存的主要问题在于,如果JVM加载了同名的类,会出现类冲突问题。解决类缓存问题的方法有多种,例如使用不同的类加载器加载同名的类,或者使用不同的命名空间来避免类冲突。 在JVM中,类加载器会将类加载到内存中...
"Jvm类加载机制详解" Jvm类加载机制是Java虚拟机(JVM)中一个非常重要的机制,它负责将编译后的Java类文件加载到JVM中,并对其进行验证、准备、解析、初始化和卸载等操作。 类加载机制的生命周期可以分为五个阶段...
JVM类加载机制是Java虚拟机运行时加载类的核心过程,它负责将.java编译后的字节码文件(.class)转换为内存中的类实例。本文详细阐述了这个机制,包括其工作流程、特点以及如何自定义类加载器。 首先,我们来看一下...
了解类加载机制对于解决这类问题至关重要,同时也有助于深入理解Java虚拟机(JVM)的工作原理。 Java 类加载机制主要由类加载器完成。JVM内置了三种预定义的类加载器: 1. **启动类加载器(Bootstrap ClassLoader...
JVM类加载机制原理及用法解析 JVM类加载机制是Java虚拟机的一个核心机制,它负责将Java类从.class文件加载到内存中,并对其进行链接、初始化等操作。在Java中,类加载机制是一个非常重要的机制,它直接关系到Java...
jvm的类加载机制详解
Java虚拟机(JVM)是Java程序运行的核心,而类加载机制则是JVM实现程序动态加载和执行的关键部分。在深入理解Java虚拟机的工作原理时,类加载机制是一个不可忽视的重要知识点。这篇博客将探讨JVM如何加载、连接和...
Java类加载机制是Java程序运行的第一步,它对于理解Java虚拟机(JVM)的行为至关重要。类加载过程涉及到类的加载、链接(验证、准备、解析)、初始化等阶段,并且这一过程是由类加载器系统完成的。 #### 二、类加载...
JVM类加载机制详解 JVM类加载机制是Java虚拟机中的一种机制,它负责加载Java类文件到内存中,以便执行Java程序。类加载机制分为五个阶段:加载、验证、准备、解析和初始化。 加载 加载是类加载过程中的一个阶段,...
通过对JVM执行子系统原理的深入分析,我们不仅了解了Class文件的具体结构和字节码指令的基本概念,还探讨了类加载机制的各个环节以及字节码执行引擎的核心组成部分。这些知识点对于深入理解JVM的工作原理、优化程序...
《JAVA-JVM-01类加载机制》 Java虚拟机(JVM)是Java程序运行的基础,其中类加载机制是其核心组成部分。本文将深入剖析Java中的类加载器和双亲委派机制,并通过示例讲解如何自定义类加载器。 类加载过程是Java程序...