0
点赞
收藏
分享

微信扫一扫

虚拟机类加载机制【类与类加载器】

亿奇学 2021-09-29 阅读 54

类加载阶段中“通过一个类的全限定名来获取描述该类的二进制字节流”这个动作放到Java虚拟机外部去实现(实现的代码叫做“类加载器(Class Loader)”),以便让应用程序自己决定如何获取所需的类。

类加载器起初是为了满足Java Applet的需求设计出来的,虽然在如今基本被淘汰,但在类层次划分、OSGi、程序热部署、代码加密等领域大放异彩,成为Java技术体系中的一块重要的基石。

  • 类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远超类加载阶段。对于任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在Java虚拟机中的唯一性,每个类加载器,都拥有一个独立的类名称空间。
  • 两个类即使来源于同一个Class文件,被同一个Java虚拟机加载,只要加载他们的虚拟机不同,那这两个类就必定不相等。
  • 这里的相等,包括代表类的Class对象的equals()方法、isAssignableForm()方法、isInstance()方法的返回结果,也包括使用instanceof关键字做对象所属关系判定等各种情况。
package com.test;

import java.io.IOException;
import java.io.InputStream;


/**
 * 类加载器与instanceof关键字
 * @author huyl
 *
 */
public class ClassLoaderTest {

    public static void main(String[] args) throws Exception {
        
        ClassLoader myLoader = new ClassLoader(){
            public Class<?>  loadClass(String name) throws ClassNotFoundException{
                try{
                    String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
                    InputStream is = (InputStream) getClass().getResourceAsStream(fileName);
                    if( is == null ){
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b,0, b.length);
                }catch(IOException e){
                    throw new ClassNotFoundException(name);
                }
            }
        };
        
        Object obj = myLoader.loadClass("com.test.ClassLoaderTest").newInstance();
        System.out.println(obj.getClass());
        System.out.println(obj instanceof com.test.ClassLoaderTest);
    }
}

输出结果

class com.test.ClassLoaderTest
false

分析原因:
这是因为Java虚拟机中同时存在了两个ClassLoaderTest类,一个是由虚拟机的应用程序类加载器所加载的,另外一个是由我们自定义的类加载器加载的,虽然他们都来自第一个Class文件,但在Java虚拟机中仍然是两个互相独立的类,做对象所属类型检查时的结果自然为false。

《深入理解Java虚拟机》学习笔记

举报

相关推荐

0 条评论