自定义类加载器的实现,类加载过程

为了安全

每个JAVA程序至少拥有三个类加载器

·引导类加载器 bootstrap

·扩展类加载器 ext

·系统类加载器(应用类加载器)app

引导类加载器负责加载系统类(rt.jar),是虚拟机不可分割的一部分,C实现的,没有对应的classloader对象

例如String.class.getClassLoader()返回null

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

系统类加载器用于加载应用类,有CLASSPATH环境变量或-classpath命令选项设置的类路径中的目录里或JAR文件里查找这些类

在oracle的java语言实现中,扩展类加载器和系统类加载器都是java实现的,都是urlclassloader类的实例

类加载器的层次结构,向上依赖加载的顺序,app会要求ext加载,ext要求bootstrap加载

JAVA的类加载是父类委托机制,先找父类加载,不行再找子类加载

这是为了害怕用户自己定义class文件然后自己写一个类加载器来加载原本应该是JVM自己加载的类,会使JVM混乱和影响用户安全。

URL url = new URL("*.jar");

URLClassLoader ucl = new URLClassLoader(new URL[]{url});

Class<?> cl = ucl.loadClass("xxx.class");

因为URLClassLoader构造器中没有指定父类加载器,因此ucl的父亲就是系统类加载器

设置线程的加载器

Thread t .....

t.setContextClassLoader(loader);

在指定类加载器的时候会用到

代码如下:

package classloader;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {

	private String name;//类加载器的名字

	private String path = "/home/chiwei/mydisk/eclipse_workspace/java/src/";//类加载的路径

	private final String fileType = ".class";

	public MyClassLoader(String name) {
		super();
		this.name = name;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	private byte[] loadClassData(String name) {
		InputStream in = null;
		byte[] data = null;
		ByteArrayOutputStream baos = null;
		try {
			name = name.replace(".", "\\");
			in = new BufferedInputStream(new FileInputStream(new File(path+name+fileType)));
			baos = new ByteArrayOutputStream();
			int ch = 0;
			while((ch=in.read())!=-1) {
				baos.write(ch);
			}
			data = baos.toByteArray();
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			try {
				baos.close();
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return data;
	}

	protected Class<?> findClass(String name) {
		byte[] data = this.loadClassData(name);
		return this.defineClass(name, data, 0,data.length);
	}

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		MyClassLoader loader1 = new MyClassLoader("loader1");
		loader1.setPath("");
		test(loader1);
	}

	public static void test(ClassLoader loader) throws Exception{
		Class<?> clazz = loader.loadClass("classloader.MyString");
		Object object = clazz.newInstance();
		MyString ms = (MyString)object;
		System.out.println(ms.toString());
		System.out.println(object==null);
		System.out.println(object.hashCode());
	}

}
package classloader;

public class MyString {

	public java.lang.String toString() {
		return "这是我自定义的String类的toString方法";
	}

}
这是我自定义的String类的toString方法
false
926509297
时间: 2024-10-06 14:33:11

自定义类加载器的实现,类加载过程的相关文章

(二十七)JVM类加载器机制与类加载过程

一.Java虚拟机启动.加载类过程分析 下面我将定义一个非常简单的java程序并运行它,来逐步分析java虚拟机启动的过程. package org.luanlouis.jvm.load; import sun.security.pkcs11.P11Util; /** * Created by louis on 2016/1/16. */ public class Main{ public static void main(String[] args) { System.out.println(

Java类加载器及Android类加载器基础

引子 Android插件化与热更新技术日渐成熟,当你研究这些技术时会发现类加载器在其中占据重要地位.Java语言天生就有灵活性.动态性,支持运行期间动态组装程序,而这一切的基础就是类加载器. Java中的类加载器 Java灵活性和动态性的原因 Java源代码被编译器编译成字节码,即从.java文件编译为.class文件,而.class文件就是通过类加载器加载到虚拟机内存中的. 虚拟机的类加载(Class Loading)过程分为加载.链接(验证.准备.解析).初始化.使用.卸载等过程.这里仅考虑

线程上下文类加载器与服务器类加载原理

双亲委派机制以及类加载器的问题 一般情况下.保证同一个类中所关联的其他类都是由当前类的类加载器所加载的. 比如,class A本身在Ext下找到.那么他里面new出来的一些类也就只能用Ext去查找了(不会低一个级别).所以有些明明App可以找到的,却找不到了. JDBC API他有实现的driver部分(mysql,sql server).我们的JDBC APl都是由Boot或者Ext来载入的.但是JDBC driver却是由Ext或者App来载入,那么就有可能找不到driver了.在Java领

JAVA类加载器二 通过类加载器读取资源文件

一.getResourceAsStream方法 getResourceAsStream方法实现如下: public InputStream getResourceAsStream(String name) { URL url = getResource(name); try { return url != null ? url.openStream() : null; } catch (IOException e) { return null; } } 可见getResourceAsStream

Java虚拟机笔记 – JVM 自定义的类加载器的实现和使用2

1.用户自定义的类加载器: 要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用. findClass protected Class<?> findClass(String name) throws ClassNotFoundException 使用指定的二进制名称查找类.此方法应该被类加载器的实现重写,该实现按照委托模型来加载类.在通过父

JVM类加载器原理与自定义类加载器

类加载器原理 JVM将class文件字节码文件加载到内存中, 并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class 对象,作为方法区类数据的访问入口. 类缓存 标准的Java SE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间.不过,JVM垃圾收集器可以回收这些Class过象. 类加载器数状结构 引导类加载器(bootstrap class loader) 它用来加载Java的核心库(JAVA_HOME/

Java虚拟机笔记 – JVM 自定义的类加载器的实现和使用

1.用户自定义的类加载器: 要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用. findClass protected Class<?> findClass(String name) throws ClassNotFoundException 使用指定的二进制名称查找类.此方法应该被类加载器的实现重写,该实现按照委托模型来加载类.在通过父

(转)JVM——自定义类加载器

背景:为什么要自定义,如何自定义,实现过程 转载:http://blog.csdn.net/SEU_Calvin/article/details/52315125 0. 为什么需要自定义类加载器 网上的大部分自定义类加载器文章,几乎都是贴一段实现代码,然后分析一两句自定义ClassLoader的原理.但是我觉得首先得把为什么需要自定义加载器这个问题搞清楚,因为如果不明白它的作用的情况下,还要去学习它显然是很让人困惑的. 首先介绍自定义类的应用场景: (1)加密:Java代码可以轻易的被反编译,如

JVM自定义类加载器加载指定classPath下的所有class及jar

一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责JAVA_HOME/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. 2.其他类加载器:由java实现,可以在方法区找到其Class对象.这里又细分为几个加载器 a).扩展类加载器(Extension ClassLoader):负责用于加载JAVA_HOM