Class.forName() 与 ClassLoader.loadClass()的区别
一、Class.forName() 方式
(1)理论
/** Called after security check for system loader access checks have been made. */
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)throws ClassNotFoundException;
/** Called after security check for system loader access checks have been made. */
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)throws ClassNotFoundException;
- 将一个Java类被有效得加载到内存中;
- 类默认会被初始化(initialize 这个参数传的是true),即执行内部的静态块代码以及保证静态属性被初始化;
- 默认会使用当前的类加载器来加载对应的类。
(2)代码说明
public class TestClass {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("Class.forName 方式加载类--->start");
Class.forName("com.jwx.digital.client.AClass").getClass();
System.out.println("Class.forName 方式加载类--->end");
}
}
class AClass {
static {
System.out.println("AClass初始化");
System.out.println("=====AClass静态代码快执行=====");
}
}
public class TestClass {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("Class.forName 方式加载类--->start");
Class.forName("com.jwx.digital.client.AClass").getClass();
System.out.println("Class.forName 方式加载类--->end");
}
}
class AClass {
static {
System.out.println("AClass初始化");
System.out.println("=====AClass静态代码快执行=====");
}
}
Class.forName 方式加载类--->start
AClass初始化
=====AClass静态代码快执行=====
Class.forName 方式加载类--->end
Class.forName 方式加载类--->start
AClass初始化
=====AClass静态代码快执行=====
Class.forName 方式加载类--->end
二、ClassLoader.loadClass方式
(1)理论
// return null if not found
private native Class<?> findBootstrapClass(String name);
// return null if not found
private native Class<?> findBootstrapClass(String name);
- 将一个java类加载到内存中;
- 类不会被初始化,只有在之后被第一次调用时类才会被初始化;因为虚拟机规范规定了,当遇到new、getstatic、putstatic或invokestatic这4条字节码指令是,如果没有进行过初始化则需要先触发初始化。
(2)代码说明
public class TestClass {
public static void main(String[] args) throws Exception {
System.out.println("ClassLoader 方式加载类--->start");
Class<?> aClass = ClassLoader.getSystemClassLoader().loadClass("com.jwx.digital.client.AClass");
System.out.println("ClassLoader 方式加载类--->end");
/* 虽然上面没有进行类的初始化,
但是虚拟机规范规定了,当遇到new、getstatic、putstatic或invokestatic这4条字节码指令是,如果没有进行过初始化则需要先触发初始化。
生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、
读取或者设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。*/
// 因此我们实例化这个class时,就会调用初始化
System.out.println("我要实例化这个类了+++++");
aClass.newInstance();
}
}
class AClass {
static {
System.out.println("AClass初始化");
System.out.println("=====AClass静态代码快执行=====");
}
}
public class TestClass {
public static void main(String[] args) throws Exception {
System.out.println("ClassLoader 方式加载类--->start");
Class<?> aClass = ClassLoader.getSystemClassLoader().loadClass("com.jwx.digital.client.AClass");
System.out.println("ClassLoader 方式加载类--->end");
/* 虽然上面没有进行类的初始化,
但是虚拟机规范规定了,当遇到new、getstatic、putstatic或invokestatic这4条字节码指令是,如果没有进行过初始化则需要先触发初始化。
生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、
读取或者设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。*/
// 因此我们实例化这个class时,就会调用初始化
System.out.println("我要实例化这个类了+++++");
aClass.newInstance();
}
}
class AClass {
static {
System.out.println("AClass初始化");
System.out.println("=====AClass静态代码快执行=====");
}
}
ClassLoader 方式加载类--->start
ClassLoader 方式加载类--->end
我要实例化这个类了+++++
AClass初始化
=====AClass静态代码快执行=====
ClassLoader 方式加载类--->start
ClassLoader 方式加载类--->end
我要实例化这个类了+++++
AClass初始化
=====AClass静态代码快执行=====
三、总结
四、补充
当一个类被主动使用时,Java虚拟机就会对其初始化,如下六种情况为主动使用:
- 当创建某个类的新实例时(如通过new或者反射,克隆,反序列化等)
- 当调用某个类的静态方法时
- 当使用某个类或接口的静态字段时
- 当调用Java API中的某些反射方法时,比如类Class中的方法,或者java.lang.reflect中的类的方法时
- 当初始化某个子类时
- 当虚拟机启动某个被标明为启动类的类(即包含main方法的那个类)
Class.forName() 与 ClassLoader.loadClass()的区别的更多相关文章
- 015 反射中的 Class.forName() 与 ClassLoader.loadClass() 的区别
作者:nnngu GitHub:https://github.com/nnngu 博客园:http://www.cnblogs.com/nnngu 简书:https://www.jianshu.com ...
- 反射中Class.forName()和ClassLoader.loadClass()的区别
一 Java类装载过程 装载:通过累的全限定名获取二进制字节流,将二进制字节流转换成方法区中的运行时数据结构,在内存中生成Java.lang.class对象: 链接:执行下面的校验.准备和解析步骤,其 ...
- Class.forName和ClassLoader.loadClass的区别
Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4. Cla ...
- 反射中的 Class.forName() 与 ClassLoader.loadClass() 的区别
在Java中,类加载器把一个类加载进Java虚拟机中,要经过三个步骤来完成:加载.链接和初始化,其中链接又可以分成验证.准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下 ...
- Class.forName和ClassLoader.loadClass的区别(转载)
Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4.Clas ...
- Class.forName和ClassLoader.loadClass区别(转)
Java中class是如何加载到JVM中的:1.class加载到JVM中有三个步骤 装载:(loading)找到class对应的字节码文件. 连接:(linking)将对应的字节码文件读入 ...
- 简单总结Class.forName("").newinstance()和new()以及classLoader.loadClass("")的区别
文章目录 背景 三种方法简单介绍 Class.forName("").newinstance()方式 new方式 classLoader.loadClass("" ...
- java两种反射的区别 - Class.forName()和ClassLoader.loadClass()
在理解这两种反射机制之前,需要弄清楚java类的加载机制. 装载:通过类的全限定名获取二进制字节流(二进制的class文件),将二进制字节流转换成方法区中的运行时数据结构,在内存中生成Java.lan ...
- Class.forName和ClassLoader.loadClass的比较【转载】
Class的装载分了三个阶段,loading,linking和initializing,分别定义在The Java Language Specification的12.2,12.3和12.4.Clas ...
随机推荐
- 浅谈SOA与RPC
一.SOA 英文名称:Service Oriented Ambiguity 中文名称:面向服务架构 SOA是一种思想,目的是提供一种设计项目的思路,让开发时更有效率. 例如原来的分布式项目中,在每个项 ...
- zz致力于变革未来的智能技术
有 R-CNN SPPNet Fast R-CNN Faster R-CNN ... 的论文翻译 现在已经不能访问了... [私人整理]空间金字塔池化网络SPPNet详解 SPP-Net是出自 ...
- WebSocket协议-基础篇
本篇文章主要讲述以下几点: WebSocket协议出现的背景 WebSocket与HTTP WebSocket API WebSocket协议出现的背景 我们在上网过程中经常用到的是HTTP和HTTP ...
- Windows下找到JVM占用资源高的线程
与linux下top命令直接显示进程下线程资源占用不同,Windows下默认任务管理器只能显示出进程的资源占用,jconsle等工具也只能显示出java进程资源占用,无法显示出进程能具体线程的资源占用 ...
- Zabbix设置邮件报警
邮件报警 概述当监控项收集了数据后,触发器会根据异常状态触发报警.根据一些报警机制,它也会通知我们一些重要的事件,而不需要我们直接在Zabbix前端进行查看.这就是通知(Notifications)的 ...
- java ++和--
public class Sample { public static void main(String[] args) { , num2 = ; , num4 = ; System.out.prin ...
- C#:ref关键字和out关键字的区别
1.在不使用关键字(比如ref关键字.out关键字等)修饰函数的情况下,大部分函数的参数是以值传递的方式,也就是说,“调用函数”在使用参数(比如myNumber)时,是把该参数复制多一份,然后将其传递 ...
- 线程池 ThreadPoolExecutor 类的源码解析
线程池 ThreadPoolExecutor 类的源码解析: 1:数据结构的分析: private final BlockingQueue<Runnable> workQueue; // ...
- 使用 Valgrind 检测 C++ 内存泄漏
Valgrind 的介绍 Valgrind 可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存.访问数组时越界.忘记释放动态内存等问题.在 Linux 可以使用下面的命令安装 Valgr ...
- centos7.x下环境搭建(五)—nginx搭建https服务
https证书获取 十大免费SSL证书 https://blog.csdn.net/ithomer/article/details/78075006 如果我们用的是阿里云或腾讯云,他们都提供了免费版的 ...