反射中Class.forName()和classLoader的区别
搞清楚两者之间区别前,我们来了解下类加载过程。
一、类加载过程
1、加载
通过一个类的全限定名来获取定义此类的二进制字节流。
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
在内存中生成一个代表这个类的Java.lang.class对象,作为方法区这个类的各种数据的访问入口。
2、验证
文件格式验证
元数据验证
字节码验证
符号引用验证
3、准备
准备阶段是正式为类变量(仅被static修饰的变量)分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。注意,这里所说的初始值“通常情况”下是数据类型的零值,“特殊情况”下是初始化真实的值,即常量值(static final)。
4、解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。注意,这个阶段不一定要有。
5、初始化
类初始化阶段是类加载过程的最后一步,真正开始执行类中定义的Java程序代码。初始化类中的所有类变量的赋值和静态语句块。
有空可以看看《【JVM基础知识】java类加载机制》
二、源码分析
1、JDK8中Class.forName()源码
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass(www.yongshiyule178.com);
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
@CallerSensitive
public static Class<?> forName(String name, boolean initialize, ClassLoader loader)
throws ClassNotFoundException
{
Class<?> caller = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// Reflective call to get caller class is only needed if a security manager
// is present. Avoid the overhead of making this call otherwise.
caller = Reflection.getCallerClass();
if (sun.misc.VM.isSystemDomainLoader(loader)) {
ClassLoader ccl www.hengtongyoule.com= ClassLoader.getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(www.gaozhuoyiqi.com)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
return forName0(name, initialize, loader, caller);
}
Class.forName(className)方法,内部实际调用的方法是forName0这个方法,在这个forName0方法中的第二个参数被默认设置为了true,这个参数代表是否对加载的类进行初始化,设置为true时会类进行初始化,代表会执行类中的静态代码块,以及对静态变量的赋值等操作。
当然,可以通过Class.forName(String name, boolean initialize,ClassLoader loader)方法来手动选择在加载类的时候是否要对类进行初始化。
2、JDK8中ClassLoader.loadClass()源码
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name,www.huarenyl.cn false);
}
ClassLoader.loadClass(className)方法,内部实际调用的方法是loadClass(name, false);
第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,即不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行。
3、结论
所以Class.forName加载类是将类进了初始化,而ClassLoader的loadClass并没有对类进行初始化,只是把类加载到了虚拟机中。
三、应用场景
1、JDBC时通常是使用Class.forName()方法来加载数据库连接驱动。因为在JDBC规范中明确要求Driver(数据库驱动)类必须向DriverManager注册自己,而注册的操作都在静态代码块中。
2、Spring框架中的IOC的实现就是使用的ClassLoader。
参考
反射中Class.forName()和ClassLoader.loadClass()的区别
在Java的反射中,Class.forName和ClassLoader的区别
反射中Class.forName()和classLoader的区别的更多相关文章
- Java反射中Class.forName和classloader的区别
Java中Class.forName和classloader都可以用来对类进行加载. Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块 ...
- 反射中Class.forName()和ClassLoader.loadClass()的区别
一 Java类装载过程 装载:通过累的全限定名获取二进制字节流,将二进制字节流转换成方法区中的运行时数据结构,在内存中生成Java.lang.class对象: 链接:执行下面的校验.准备和解析步骤,其 ...
- 在Java的反射中,Class.forName和ClassLoader的区别
前言 最近在面试过程中有被问到,在Java反射中Class.forName()加载类和使用ClassLoader加载类的区别.当时没有想出来后来自己研究了一下就写下来记录一下. 解释 在java中Cl ...
- 反射中,Class.forName 和 classloader 的区别
https://blog.csdn.net/qq_27093465/article/details/52262340 java中class.forName()和classLoader都可用来对类进行加 ...
- 在 Java 的反射中,Class.forName 和 ClassLoader 的区别
1. 解释 在java中Class.forName()和ClassLoader都可以对类进行加载.ClassLoader就是遵循双亲委派模型最终调用启动类加载器的类加载器,实现的功能是“通过一个类的全 ...
- Class.forName和ClassLoader的区别
一 看名字就知道了,一个是类的创建,一个类加载器 二 再看下Class.forName源码,调用了ClassLoader @CallerSensitive public static Class< ...
- class.forName 和 classLoader的区别
Java中的Class.forName()和ClassLoader都可以用来对类进行加载.Class.forName()除了将类的.class文件加载到JVM中 还会对类进行解释,执行类中的stati ...
- class.forName() 和 classLoader 的区别
相同点: java中class.forName() 和 classLoader 都可用来对类进行加载 不同店: 1.class.forName()除了将类的 .class ...
- java反射中,Class.forName和classloader的区别
http://blog.csdn.net/qq_27093465/article/details/52262340
随机推荐
- BOM、DOM
window对象 所有浏览器都支持window对象,他表示浏览器窗口. 全局变量是window对象的属性.全局函数是window对象的方法. window的常用方法: window.innerHeig ...
- [转帖]IP /TCP协议及握手过程和数据包格式中级详解
IP /TCP协议及握手过程和数据包格式中级详解 https://www.toutiao.com/a6665292902458982926/ 写的挺好的 其实 一直没闹明白 网络好 广播地址 还有 网 ...
- flutter图片铺满父框
正常我们需要显示一张图片,会用到Image这个控件. 打个比方,我们加载一张本地的图片, 先看一下这个Image.asset的源码: Image.asset(String name, { Key ke ...
- socket基础编程-1
server端和client端 1.server端: import socket server=socket.socket() server.bind(('localhost',8080)) serv ...
- php-memcached详解
一.memcached 简介 在很多场合,我们都会听到 memcached 这个名字,但很多同学只是听过,并没有用过或实际了解过,只知道它是一个很不错的东东.这里简单介绍一下,memcached 是高 ...
- CDH 6.0.1 集群搭建 「Before install」
从这一篇文章开始会有三篇文章依次介绍集群搭建 「Before install」 「Process」 「After install」 继上一篇使用 docker 部署单机 CDH 的文章,当我们使用 d ...
- kibana——es的批量操作
一·_mget: 1.创建的索引如下: 2.批量查询: #查询两个 GET _mget { "docs":[ { "_index":"testdb&q ...
- centos7系统管理和运维实战——运维必备的网络管理技能(1)
运维必备的网络管理技能 一.网络管理协议: 1.简单的两个概念: DHCP(动态主机配置协议):如果网络结构要更改,需要从新初始化网络参数,手机用动态主机配置协议可以避免这个问题.客户端可以从D ...
- Linux基础学习(10)--Shell基础
第十章——Shell基础 一.Shell概述 1.Shell是什么: (1)Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来 ...
- 运维常用mysql语句
1..select @@version; ##查询当前mysql的版本. 2. show variables like 'port';##查看mysql实例的端口. 3.show variables ...