Java虚拟机-02:类与类加载器

2019-05-17 11:14:55 浏览数 (1)

摘要:本文主要介绍类加载器、类的唯一性、启动类加载器、拓展类加载器、应用程序类加载器。

内容目录:

1.类加载器

把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”的这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类,实现这个动作的代码模块称为“类加载器”;

2.类的唯一性

对于任意一个类,都需要由加载它的类加载器和这个类本身这两点一同确定其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话也可以理解为:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载他们的类的加载器不同,那么,这两个类必定不相等。

这个相等,包含代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括使用instanceof关键字做对象所属关系判定等情况。

在Java虚拟机中,从Java虚拟机的角度看,有两种不同的类加载器:

启动类加载器(Bootstrap ClassLoader),这个类加载器使用C 语言实现的,是虚拟机自身的一部分;

这种分类是大方向上的,除了启动类加载器,其他的类加载器都是非启动类加载器,这些类加载器是Java语言实现的,独立于虚拟机外部,并且全都继承自抽象类java.lang.ClassLoader。

从Java开发人员的角度看,类加载器可以再细分一下,绝大部分Java程序都会使用到以下3种系统提供的类加载器:

3.启动类加载器 Bootstrap ClassLoader

这个类加载器负责将存放在<JAVA_HOME>lib目录中的,或者被-Xbootclasspath参数指定的路径中的,并且是虚拟机识别(这里说的识别,仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)的类库加载到虚拟机内存中。启动类加载器无法被Java程序直接使用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可。

4.拓展类加载器 Extension ClassLoader

扩展类加载器是由sun.misc.Launcher$ExtClassLoader实现的,由Java语言实现的,是Launcher的静态内部类,它负责加载:

开发者可以直接使用扩展类加载器。

Launcher.class中的部分代码:

代码语言:javascript复制
    public class Launcher {	
      static class ExtClassLoader extends URLClassLoader {	
        public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {	
            final File[] var0 = getExtDirs();	
	
            try {	
                return (Launcher.ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<Launcher.ExtClassLoader>() {	
                    public Launcher.ExtClassLoader run() throws IOException {	
                        int var1 = var0.length;	
	
                        for(int var2 = 0; var2 < var1;   var2) {	
                            MetaIndex.registerDirectory(var0[var2]);	
                        }	
	
                        return new Launcher.ExtClassLoader(var0);	
                    }	
                });	
            } catch (PrivilegedActionException var2) {	
                throw (IOException)var2.getException();	
            }	
        }	
       ......	
       }	
     }

5.应用程序类加载器 Application ClassLoader

应用程序类加载器是由sun.misc.Launcher$AppClassLoader实现的,由Java语言实现,由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以也称为系统类加载器,它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器。

ClassLoader.class中的部分代码:

代码语言:javascript复制
public abstract class ClassLoader {	
    private static java.lang.ClassLoader scl;	
    @CallerSensitive	
    public static java.lang.ClassLoader getSystemClassLoader() {	
        initSystemClassLoader();	
        if (scl == null) {	
            return null;	
        }	
        SecurityManager sm = System.getSecurityManager();	
        if (sm != null) {	
            checkClassLoaderPermission(scl, Reflection.getCallerClass());	
        }	
        return scl;	
    }	
    ......	
}

如果应用程序中没有自定义过自己的类加载器,一般情况下就是程序中默认的类加载器。

0 人点赞