栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM中class对象加载方式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM中class对象加载方式

文章目录
  • 1 class对象详解
  • 2 Class.forName和ClassLoader.loadClass区别
    • 2.1 jvm加载class步骤
    • 2.2 两种方式的详细方法
    • 2.3 两种方式的区别
    • 2.4 举例说明他们各自的使用方法

1 class对象详解

java中把生成Class对象和实例对象弄混了,更何况生成Class对象和生成instance都有多种方式。所以只有弄清其中的原理,才可以深入理解。首先要生成Class对象,然后再生成Instance。那Class对象的生成方式有哪些呢,以及其中是如何秘密生成的呢?
Class对象的生成方式如下:

  1. Class.forName("类名字符串") (注意:类名字符串必须是全称,包名+类名)
  2. 类名.class
  3. 实例对象.getClass()

通过一段小程序,来观察一下Class对象的生成的原理。

  
    
  public class TestClass {    
public  static void main(String[] args)  {    
try {    
//测试Class.forName()  
  Class testTypeForName=Class.forName("TestClassType");          
  System.out.println("testForName---"+testTypeForName);  
  //测试类名.class  
  Class testTypeClass=TestClassType.class;  
  System.out.println("testTypeClass---"+testTypeClass);  
  //测试Object.getClass()  
  TestClassType testGetClass= new TestClassType();  
  System.out.println("testGetClass---"+testGetClass.getClass());  
  
 } catch (ClassNotFoundException e) {  
  // TODO Auto-generated catch block  
  e.printStackTrace();  
  }  
}  
  
}  
   class TestClassType{  
  //构造函数  
  public TestClassType(){  
  System.out.println("----构造函数---");  
  }  
  //静态的参数初始化  
  static{  
  System.out.println("---静态的参数初始化---");  
  }  
  
//非静态的参数初始化  
  {  
  System.out.println("----非静态的参数初始化---");  
  }          
  }  

测试的结果如下:
---静态的参数初始化---
testForName---class TestClassType
testTypeClass---class TestClassType
----非静态的参数初始化---
----构造函数---
testGetClass---class TestClassType

根据结果可以发现,三种生成的Class对象一样的。并且三种生成Class对象只打印一次静态的参数初始化。
我们知道,静态的方法属性初始化,是在加载类的时候初始化。而非静态方法属性初始化,是new类实例对象的时候加载。
因此,这段程序说明,三种方式生成Class对象,其实只有一个Class对象。在生成Class对象的时候,首先判断内存中是否已经加载。

所以,生成Class对象的过程其实是如此的:当我们编写一个新的java类时,JVM就会帮我们编译成class对象,存放在同名的.class文件中。在运行时,当需要生成这个类的对象,JVM就会检查此类是否已经装载内存中。若是没有装载,则把.class文件装入到内存中。若是装载,则根据class文件生成实例对象。

2 Class.forName和ClassLoader.loadClass区别 2.1 jvm加载class步骤

Java中class是如何加载到JVM中的:
class加载到JVM中有三个步骤:

  • 装载:(loading)找到class对应的字节码文件。
  • 连接:(linking)将对应的字节码文件读入到JVM中。
  • 初始化:(initializing)对class做相应的初始化动作。
2.2 两种方式的详细方法

Java中两种加载class到JVM中的方式

  • Class.forName("className");
    其实这种方法调运的是:Class.forName(className, true,ClassLoader.getCallerClassLoader())方法
    参数一:className,需要加载的类的名称。
    参数二:true,是否对class进行初始化(需要initialize)
    参数三:classLoader,对应的类加载器

  • ClassLoader.laodClass("className");
    其实这种方法调运的是:ClassLoader.loadClass(name, false)方法
    参数一:name,需要加载的类的名称
    参数二:false,这个类加载以后是否需要去连接(不需要linking)

2.3 两种方式的区别

forName("")得到的class是已经初始化完成的
loadClass("")得到的class是还没有连接的
一般情况下,这两个方法效果一样,都能装载Class。
但如果程序依赖于Class是否被初始化,就必须用Class.forName(name)了。

2.4 举例说明他们各自的使用方法

java使用JDBC连接数据库时候,我们首先需要加载数据库驱动。

Class.forName("com.mysql.jdbc.Driver");//通过这种方式将驱动注册到驱动管理器上
Connection conn = DriverManager.getConnection("url","userName","password");//通过驱动管理器获得相应的连接

查看com.mysql.jdbc.Driver源码:

public class Driver extends NonRegisteringDriver
  implements java.sql.Driver
{
    //注意,这里有一个static的代码块,这个代码块将会在class初始化的时候执行
  static
  {
    try
    {
        //将这个驱动Driver注册到驱动管理器上
      DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
      throw new RuntimeException("Can't register driver!");
    }
  }
}

Class.forName("com.mysql.jdbc.Driver")方法以后,他会进行class的初始化,执行static代码块。
也就是说class初始化以后,就会将驱动注册到DriverManageer上,之后才能通过DriverManager去获取相应的连接。
但是要是我们使用ClassLoader.loadClass(com.mysql.jdbc.Driver)的话,不会link,更也不会初始化class。相应的就不会回将Driver注册到DriverManager上面,所以肯定不能通过DriverManager获取相应的连接。
附录:JVM加载class文件原理

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/346535.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号