`
beyondqinghua
  • 浏览: 42390 次
  • 性别: Icon_minigender_1
  • 来自: 南昌
社区版块
存档分类
最新评论

认识java的类加载器(一)

    博客分类:
  • JSE
阅读更多

1、认识类装载器:

类装入组件是 JAVA 虚拟机的基础,其是一个重要的、但又常常被我们忽略的 JAVA 运行时系统组件。它是负责在运行时查找和装入类文件的类,因此创建自己的 ClassLoader 可以非常方便的定制 JVM

JAVA编译的程序是一种特殊的、独立于平台的格式,并非依赖于它们所运行的平台。JAVA编译的类文件在运行时并非立即全部都装入内存,而是根据程序需要装入内存,有点类似我们操作系统的虚拟存储管理,根据。ClassLoader JVM 中将类装入内存的那部分。

JAVA的类加载器本身就是用 JAVA编写的,这意味着创建您自己的 ClassLoader 非常容易,不必了解 JVM的低层细节。

那么为什么要创建自己的类加载器呢,主要是由于JAVA默认的类加载器只能加载本地的类文件,这与JAVA的网络特性非常的不合,因此,有必要根据需要修改JAVA的类加载器方便的从网络加载类文件。

有许多其它方式可以获取类文件。除了简单地从本地或网络装入文件以外,可以使用定制的 ClassLoader 完成以下任务:

n        在执行非置信代码之前,自动验证数字签名

n        使用用户提供的密码透明地解密代码

n        动态地创建符合用户特定需要的定制化构建类

任何您认为可以生成 JAVA 字节码的内容都可以集成到应用程序中。

每个 Class 对象都包含一个对定义它的 ClassLoader 引用

数组类的 Class 对象不是由类加载器创建的,而是由 Java 运行时根据需要自动创建。数组类的类加载器由 Class.getClassLoader() 返回,该加载器与其元素类型的类加载器是相同的;如果该元素类型是基本类型,则该数组类没有类加载器。

2、如何定制ClassLoader

我相信编写过Applet程序的朋友都知道,通过Http协议我们可以从远程服务器上下载JAVA字节代码进行加载运行,这都归功与JAVA的自定义类加载器,Applet查看器内置了一个类加载器,它不是在本地加载类文件,而是通过Http协议从网络中加载。同时这个加载器还可以做其它事情,通过JAVA的沙箱来限制Applet的安全范围,并且不干扰其他的Applet程序。

类加载器ClassLoader是负责加载类的对象。ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。

ClassLoader 类使用委托模型来搜索类和资源。每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作 ClassLoader 实例的父类加载器。

实例代码:

 

import java.io.*;

class NetworkClassLoader extends ClassLoader {
    
    private String host;
    private int port;
    
    public static void main(String[] args)throws Exception{
		
		 ClassLoader loader = new NetworkClassLoader("127.0.0.1", 4444);
         Object pig = loader.loadClass("Pig.class").newInstance();
	}
    
    public NetworkClassLoader(){
    }
    
    public NetworkClassLoader(String host,int port){
    	this.host = host;
    	this.port = port;
    }
    
    //类加载器
    public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException{
    	// 目标Class
        Class clas = null;

        // 看是否已经加载该类
        clas = findLoadedClass( name );
        
        
        if(clas == null){
        	clas = findClass(name);
        }
        
        //如果class对象不存在则在系统中查找
        if (clas==null) {
          clas = findSystemClass( name );
        }
        
        if(clas == null){
        	
        	throw new ClassNotFoundException("该类不存在1");
        }
        
        //是否需要分析该类
        if (resolve && clas != null)
            resolveClass( clas );
        return clas;
     }
    
    //构造该类的Class对象
    public Class findClass(String name){
    	try{
            byte[] b = loadClassData(name);
            if(b == null){
            	return null;
            }
            System.out.println("my findClass method");
            
            return defineClass("Pig", b, 0, b.length);
            
        }catch(IOException e){
        	System.out.print(e.getMessage());
        }
        return null;
    }
    
    //从网络加载加载类的二进制代码,此处我们使用本地文件
    private byte[] loadClassData(String name)throws IOException{
        
        //读取类文件
        File file = new File(name);
        if(!file.exists()){
        	return null;
        }
        FileInputStream input = new FileInputStream(file);
        long length = file.length();
        byte[] bt = new byte[(int)length];
        
        int rl = input.read(bt);
        
        if(rl != length){
        	throw new IOException("不能读取所有内容");
        }
        input.close();
        
        return bt;
    }
}

 

Class loadClass( String name, boolean resolve )方法ClassLoader 的入口点。

使用指定的二进制名称来加载类。此方法的默认实现将按以下顺序搜索类:

l        调用 findLoadedClass(String) 来检查是否已经加载类。

l        在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。

l        调用 findClass(String) 方法查找类。

l        如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 resolveClass(Class) 方法。

鼓励用 ClassLoader 的子类重写 findClass(String),而不是使用此方法。

finalClass<?>defineClass(String name,byte[] b,int off,int len)方法 ClassLoader 的主要功能部件。该方法接受由编译后的字节的数组并把它转换成 Class对象。原始数组包含如从文件系统或网络装入的数据。

defineClass 管理 JVM 的许多复杂、神秘和倚赖于实现的方面 -- 它把字节码分析成运行时数据结构、校验有效性等等,类似编译器的自动机。而且你没有办法重写这个方法,正如你看到的,他是final类型。

final Class<?> findSystemClass(String name)方法从本地classpath中装入文件。它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象,以将该文件转换成类。当运行 Java 应用程序时,这是 JVM的缺省类文件装载机制。

final Class<?> findLoadedClass(String name)方法用来判断类加载器是否已经加载了该类,避免不必要的资源浪费,建议首先调用该方法。

分享到:
评论

相关推荐

    深入探讨 Java 类加载器

    Java 类加载器体系是一个树状结构,主要由以下几部分组成: - **引导类加载器(Bootstrap ClassLoader)**:加载JRE的核心类库,如rt.jar。 - **扩展类加载器(Extension ClassLoader)**:加载JRE的扩展库,位于jre...

    Java类加载原理浅析

    这是Java类加载器遵循的一种策略,它保证了类的唯一性。当一个类加载器接收到加载类的请求时,它首先会委托父加载器去尝试加载,只有当父加载器无法完成时,子加载器才会尝试自己加载。这种模型避免了类的重复加载,...

    认识Java的Class类.doc

    有两个版本,一个是接受字符串参数,另一个接受字符串、布尔值和类加载器参数。布尔值参数表示是否需要初始化类,如果不为true,那么类的静态初始化器不会被执行,直到类被首次实例化。 6. **获取类的信息**:Class...

    第一章认识Java.

    由标题“第一章认识Java”以及描述中的“Java发展”,我们可以从中提炼出关于Java的基本信息及其发展历程的关键点。 ##### 历史背景 - **开始研究**:Java项目始于1990年,最初由Sun Microsystems发起。 - **Oak**...

    JVM实战-JVM类加载机制案例分析

    通过实践操作,掌握类的加载、连接与初始化过程,了解不同类型的类加载器及其工作原理,学会创建自定义的类加载器,并对类的卸载有所认识。实验将结合具体的Java程序实例,运用单例模式对静态变量和对象进行初始化,...

    java基础讲义-帮助大家简单认识JAVA

    字节码加载器负责加载代码,字节码校验器则检查代码是否符合安全规范,防止恶意代码的执行。Java还提供了多线程支持,通过Thread类可以轻松创建和管理多个并发执行的线程,实现程序的并行性和实时交互。 Java的可...

    JAVA工程师实习一周总结【推荐下载】.doc

    这一周的实习让我对JAVA开发有了更深入的理解,特别是对Java虚拟机(JVM)和类加载器(ClassLoader)机制有了初步的认识。 Java虚拟机是Java语言运行的基础,它负责管理程序的内存空间,包括堆内存、栈内存、方法区...

    《 从NoSuchMethodError看jvm编译和class加载方式》的测试项目代码

    JVM(Java虚拟机)采用“双亲委派模型”加载类,即当一个类被加载时,它会首先尝试由启动类加载器(Bootstrap ClassLoader)加载,如果该类不在启动类加载器的路径中,则会委托给扩展类加载器(Extension ...

    Java做的幻灯片

    在Java AWT(Abstract Window Toolkit)库中,`MediaTracker`是用来管理图像加载和显示的一个关键工具。在处理图形或者媒体文件时,尤其是像幻灯片这样需要展示多个图片的场景,`MediaTracker`能确保图片完全加载到...

    Java虚拟机规范中文版.pdf

    类加载器在运行Java程序时按需加载类,这允许Java程序进行延迟加载,即仅在需要时才加载类,这有助于优化程序的启动时间和运行时性能。 JVM还提供了执行安全检查的能力,包括数组边界检查和类型检查等,这有助于...

    《JAVA语言程序设计》期末考试试题及答案_java期末考试_java_

    1. **Java基础知识**:包括Java的历史、特点、运行机制(JVM)、类加载器以及Java与其他编程语言的对比。这部分会考察对Java的基本认识和理解。 2. **语法基础**:涉及变量、数据类型、运算符、流程控制(如if语句...

    认识Java(共35张PPT).pptx

    例如,一个简单的Java程序可能包括注释、类定义、变量声明、方法定义以及主方法中的逻辑代码。 在DOS环境下,开发者可以使用简单的命令行指令,如REN(重命名文件),来管理和操作文件。对于初学者,理解这些基础...

    java学习心得

    当类加载器返回null时,意味着使用了Bootstrap ClassLoader,因为它是由C++实现的,没有对应的Java类加载器。 3. JDK与JRE的区别 JRE(Java Runtime Environment)是运行Java程序所需的环境,包括Java虚拟机(JVM)...

    java写的入门文本编辑器

    Java编写的入门文本编辑器是一个非常适合初学者上手的项目,它可以帮助你深入理解JAVA语言的基础概念、核心语法以及面向对象编程的基本原理。通过实际编写这样一个应用,你可以体验到JAVA的强大功能并逐步熟悉开发...

    Java雷电游戏,主要用SWING和Java的进程,纯Java代码写的,主要为开发人员对Java线程的认识

    Java雷电游戏是一款基于SWING图形用户界面库和Java进程管理技术开发的纯Java应用程序,旨在帮助开发者加深对Java线程的理解。通过分析这款游戏的源代码,我们可以学习到多个Java编程的重要知识点。 首先,SWING是...

    大白话带你认识JVM.pdf

    类加载器是JVM的一个关键组件,它的任务是将.java源文件编译成的.class字节码文件加载到JVM中。类加载器分为不同的层次,如引导类加载器、扩展类加载器和应用程序类加载器,它们共同协作完成类的加载工作。加载的类...

Global site tag (gtag.js) - Google Analytics