Java类的加载过程与ClassLoader的理解及测试

时间:2022-12-13 13:50:35

先了解下在程序准备运行某个类,但是该类还没被加载到内存中,会经过以下三个步骤:

类的加载(Load)→类的连接(Link)→类的初始化(Initialize)

  • 加载:类经过javac.exe编译的.class字节码文件读入内存(将静态数据转换成堆中方法区的运行时数据结构),并为之创建一个java.lang.Class对象作为方法区中类数据的访问入口(引用的地址),需要访问和使用类数据只能通过这个Class对象;此过程由类的加载器完成;
  • 链接:将java类的二进制代码合并到JVM的运行状态中的过程;
    • 验证:确保加载的类符合JVM规范;
    • 准备:正式为类变量(static)分配内存并设置变量默认初始值(非任何显示赋值),这些内存都在方法区中分配;
    • 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
  • 初始化:JVM负责对类进行初始化;
    • 执行类构造器()方法的: 此方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的(类构造器是构造类信息的,并非new对象构造器)
    • 如其父类为进行初始化,则初始化操作从先从父类进行;
    • 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步;

类加载器ClassLoader的作用:

除了上面提到的作用,还有一个类缓存机制:一旦某个类被加载到内存中,将位置加载(缓存)一段时间,相当于一个缓存了一个Class对象,无论此类创建多少个实例,都是从这唯一的结构中获取信息;GC也可以回收这些Class对象;

JVM规范定义的类的加载器类型如下:

Java类的加载过程与ClassLoader的理解及测试

加载器关系测试:

@Test
public void test1() {
//1.获取一个系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//2.获取系统类加载器的父类加载器,即扩展类加载器
ClassLoader extensionClassLoader = systemClassLoader.getParent();
System.out.println(extensionClassLoader);
//3.获取扩展类加载器的父类加载器,即引导类加载器
ClassLoader bootstapClassLoader = extensionClassLoader.getParent();
//引导类加载器用于加载java核心库,无法直接获取,故输出null
System.out.println(bootstapClassLoader);
//4.测试当前类由哪个类加载器进行加载
ClassLoader classLoader = null;
try {
classLoader = Class.forName("Reflection.ClassLoaderTest").getClassLoader();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(classLoader);//结果为系统类加载器
//5.测试JDK提供的Object类由哪个类加载器完成
ClassLoader objClassLoader = null;
try {
objClassLoader = Class.forName("java.lang.Object").getClassLoader();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(objClassLoader);//结果为null(说明是用的引导类加载器,我们无法获取)
//6.关于类加载器的一个主要方法:getResourceAsStream(String str):获取路径下的指定文件的输入流
InputStream is = null;
is = this.getClass().getClassLoader().getResourceAsStream("Reflection\\test.properties");
System.out.println(is);
//可用于读取配置文件,下面单独拿来测试
}

读取.properties配置文件:

    @Test
public void test2(){
Properties properties = new Properties();//表示一个持久的属性集,可保存在流中或从流中加载
// //1.获取输入流
// //方式一:(此时的文件默认路径在Module下)
// FileInputStream fis = null;
// try {
// fis = new FileInputStream("test.properties");
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
//方式二:使用ClassLoader方式(此时的文件默认路径在当前Module的src下)
//获取当前类的Class实例对象-获取类加载器-获取指定指定路径下的文件输入流
InputStream is = this.getClass().getClassLoader().getResourceAsStream("test1.properties"); //2.读取配置文件
try {
//从输入流中读取属性列表(键和元素对)
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//匹配对应key的属性,获取key对应的元素值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println("user = " + user + " , password = " + password);
}

Java类的加载过程与ClassLoader的理解及测试的更多相关文章

  1. Java类的加载过程-重点!!

    java类的加载过程有以下几步共同完成: 加载->连接->初始化.连接又分为验证.准备.解析 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以 ...

  2. java 反射,类的加载过程以及Classloader类加载器

    首先自定义一个类Person package reflection; public class Person { private String name; public int age; public ...

  3. java类的加载过程

    1.类的加载顺序 (1)JVM在首次加载类时会对  静态初始化块.静态成员变量. 静态方法进行一次初始化. (2)只有在调用new方法时才会创建类的实例. (3)对象创建过程: 首先执行父类(如果有) ...

  4. Java 类的加载过程(阿里面试题)

    问以下程序打印出什么内容: 问题及解析如下: /** * 加载方法不等于执行方法,初始化变量则会赋值 * 类加载顺序应为 加载静态方法-初始化静态变量-执行静态代码块 * 实例化时 先加载非静态方法- ...

  5. Java类的加载、链接和初始化

    一.Java的类加载机制回顾与总结: 我们知道一个Java类要想运行,必须由jvm将其装载到内存中才能运行,装载的目的就是把Java字节代码转换成JVM中的java.lang.Class类的对象.这样 ...

  6. 别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】

    目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...

  7. java类从加载、连接到初始化过程

    类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个Class对象,存储在.class文件中,JV ...

  8. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  9. JVM——类的加载过程

    附一张图方便理解,一个类的执行过程 类的加载过程,简明的来说 类装饰器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: 装载:查 ...

随机推荐

  1. 模块化你的JS代码

    为什么要使用模块模式? 因为在全局作用域中声明的变量和函数都自动成为全局对象Window的属性,这经常会导致命名冲突,还会导致一些非常重要的可维护性难题,全局变量越多,引入错误BUG的概率就越大!所以 ...

  2. C盘更改文件夹权限

    现象:点“安全”添加用户并允许所有权限后,点击“应用”,弹出“无法保存对xxxxx权限所在的更改.拒绝访问”对话框 解决方法:点击“安全”-->"高级"-->“所有者” ...

  3. BasicModal - 简单易用的现代 Web App 弹窗

    BasicModal 是为现代 Web 应用程序打造的弹窗系统.它包括所有你需要显示的信息,问题或接收用户的输入.这里的弹窗还可以链接起来,所以你可以很容易地建立一个预定义顺序的安装帮助或显示对话框. ...

  4. [转]JVM内存堆布局图解分析

    JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢 ...

  5. Redis部分数据结构方法小结

    package com.practice.util; import java.util.HashMap; import java.util.List; import java.util.Map; im ...

  6. 科学家有了钱以后,真是挺吓人的——D.E.Shaw的牛逼人生

    科学家有了钱以后,真是挺吓人的——D.E.Shaw的牛逼人生 黑科技,还是要提D.E.Shaw Research这个奇异的存在. 要讲这个黑科技,我们可能要扯远一点,先讲讲D.E. Shaw这个人是怎 ...

  7. 简单版问卷调查系统(Asp.Net+SqlServer2008)

    1.系统主要涉及以下几个表  问卷项目表(Q_Naire) 问卷题目表(Q_Problem) 题目类型表(Q_ProblmeType) 题目选项表(Q_Options) 调查结果表(Q_Answer) ...

  8. shell-输入与输出<echo, read, cat, tee >

    1. echo echo命令可以显示文本行或变量,或者吧字符串输入到文件. 用法:echo [option] string   #[option]可选:-e ==>解析转移字符,(常用的\n & ...

  9. linux虚机配置开发/Server环境全集

    linux虚机配置开发/Server环境全集 9. centos 升级githttp://www.cnblogs.com/grimm/p/5368777.htmla. 下载git2.2.1并将git添 ...

  10. oracle中并行执行不一定比串行执行快

    并行执行与串行执行相比,能否缩短执行时间,取决于如下几个方面:1.待执行的目标SQL是否适合并行执行,有些SQL是不太适合并行执行的,比如走索引的嵌套循环连接.2.数据库服务器上的硬件资源(如CPU. ...