您的位置:首页 > 运维架构 > 网站架构

【Java 安全技术探索之路系列:J2SE安全架构】之五:类加载器

2015-06-10 09:39 691 查看
作者:郭嘉

邮箱:allenwells@163.com

博客:http://blog.csdn.net/allenwells

github:https://github.com/AllenWells

【Java 安全技术探索之路系列:J2SE安全架构】章节列表

【Java安全技术探索之路系列:J2SE安全架构】之一:J2SE安全架构开篇

【Java 安全技术探索之路系列:J2SE安全架构】之五:类加载器

【Java 安全技术探索之路系列:J2SE安全架构】之六:安全管理工具

一 类加载器的作用

1.1 名字空间的隔离(Name Space Separation)

把名字空间隔离以防止有意或无意的名字冲突问题。

1.2 包边界保护(Package Boundary Protection)

类加载器拒绝加载不可靠的类到核心Java包中,这些核心包包含可靠的系统类和其他受限包。

1.3 访问权限分配(Access Right Assignment)

类加载器有能力把每个被加载的类和一组授权关联起来,授权被描述为java.security.Permission类型对象。

1.4 搜索顺序的加强(Search order Enforcement)

类加载机制加强搜索顺序,以防止可靠的类被来自不太可靠的源中的类替换。

二 类加载器的分类

类加载器有一种父子关系,除了引导类加载器,每个类都有一个父类加载器,可以通过getParent()方法获得,根据规定,类加载器会为它的父类加载器提供一个机会,以便加载任何给定的类,并且只有父类加载失败时,子类才会去加载给定的类,这种关系也称为代理模式.

类加载器作为命名空间

Java程序中包名的存在是为了消除名字的冲突,而在同一个虚拟机中,可以有两个类,它们的类名和包名都是相同的,类是由它的全名和类加载器来确定的。这些名字相同的类可以被彻底的区分开而没有任何冲突,虚拟机是通过java类的全名和它的类加载器来区分一个java类的

为什么使用代理模式

所有Java应用都至少引用java.lang.Object类,也就是在运行的时候,java.lang.Object这个类需要被加载到Java虚拟机中,如果这个加载过程由Java自己的类加载器来完成,则在虚拟机中会存在多个版本的java.lang.Object类,而且这些类是不兼容的,代理模式就是为了保证Java核心库的类型安全

类加载器的树状图如下所示:

类加载器的树状图Visio源文件下载



2.1 系统类加载器

2.1.1 引导类加载器

引导类加载器负责加载系统类,通常从JAR文件rt.jar中进行加载,它是虚拟机整体中的一部分,通常是用C语言来实现的,引导类加载器没有对应的ClassLoader对象。

2.1.2 扩展类加载器

扩展类加载器用于从jre/lib/ext目录加载标准的扩展,可以将JAR文件放入该路径,这样即使没有任何类路径,扩展类加载器也可以找到其中的各个类。

注意:如果将JAR文件放入jre/lib/ext目录中,并且它的类中有一个类需要调用系统类或者扩展类,那么就会遇到麻烦,扩展类加载器并不使用类路径,在使用扩展目录类解决类文件的冲突之前,要牢记这种情况。

2.1.3 系统类加载器

系统加载器根据Java应用的类路径(CLASSPATH)来加载Java类,一般来说Java应用的类都是由它来加载的,可以通过ClassLoader.getSystemclassloader()来获取它。

**上下文类加载 .3

.器**

每一个线程都有一个对类加载器的引用,称为上下文类加载器。主线程的上下文类加载器是系统类加载器,当新线程创建时,它的上下文加载器就会被设置成为创建线程的上下文类加载器。因此,如果你不做任何特殊的操作,所有线程的类加载器都会被设置成为系统类加载器。我们也可以通过以下方式为线程设置任何类型的类加载器。

设置类加载器

Thread thread = Thread.currentThread();
thread.setContextClassLoader(loader);


获取类加载器

Thread thread = Thread.currentThread();
ClassLoader loader = thread.getContextClassLoader();
Class class = loader.loadClass(className);


2.2 自定义类加载器

自定义类加载器用来实现某些特殊目的,比如类加密或类检查等。要编写自己的类加载器,只需要继承ClassLoader类,并实现其中的FindClass(String className)方法即可。

FindClass(String className)方法的实现需要做到以下两点:

为来自本地文件系统或其他来源的类加载其字节码。

调用ClassLoader超类的defineClass()方法,向虚拟机提供字节码。

举例:下面写一个文件系统类加载器,该加载器可以加载存储在文件系统上的Java字节码。

public class FileSystemClassLoader extends ClassLoader { 

    private String rootDir; 

    public FileSystemClassLoader(String rootDir) { 
        this.rootDir = rootDir; 
    } 

    protected Class<?> findClass(String name) throws ClassNotFoundException { 
        byte[] classData = getClassData(name); 
        if (classData == null) { 
            throw new ClassNotFoundException(); 
        } 
        else { 
            return defineClass(name, classData, 0, classData.length); 
        } 
    } 

    private byte[] getClassData(String className) { 
        String path = classNameToPath(className); 
        try { 
            InputStream ins = new FileInputStream(path); 
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
            int bufferSize = 4096; 
            byte[] buffer = new byte[bufferSize]; 
            int bytesNumRead = 0; 
            while ((bytesNumRead = ins.read(buffer)) != -1) { 
                baos.write(buffer, 0, bytesNumRead); 
            } 
            return baos.toByteArray(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
        return null; 
    } 

    private String classNameToPath(String className) { 
        return rootDir + File.separatorChar 
                + className.replace('.', File.separatorChar) + ".class"; 
    } 
 }


三 类的加载流程

Java类加载器负责加载Java类字节码到Java虚拟机中。一般说来,类的编译和加载会经过以下几个流程。

注:MyClass表示加载的类

装载:查找并加载类的二进制数据。

链接

验证:确保被加载类的正确性。

准备:为类的静态变量分配内存,并将其初始化为默认值。

解析:把类中的符号引用转换为直接引用。

初始化:为类的静态变量赋予正确的初始值。

创建类的实例。

访问某个类或接口的静态变量,或者对该静态变量赋值。

反射:Class.forName(“com.allenwells.MyBlog”);

初始化父类,初始化父类的子类。

JVM启动时标明的启动类(即文件名和类名相同的那个类),此种情况下才会导致类的初始化,

如果这个类没有被加载和链接,那就先进行加载和链接。

如果这个类存在直接父类,并且这个类还没有初始化(在一个类加载器中,类只能被初始化一次),那就先初始化直接父类(不适用于接口)。

加入类中存在的初始化语句(如static变量和static块),那就先执行这些初始化语句。

加载类:具体流程如下图所示:

类加载流程图Visio源文件下载

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: