Java基础-知识点总结-Java类加载器,java-java
Java基础-知识点总结-Java类加载器,java-java
Java类加载器
类加载器(classloader)用来加载 Java 类到 Java虚拟机中。一般来说,Java虚拟机使用 Java类的方式如下:Java源程序(.java文件)在经过 Java编译器编译之后就被转换成 Java字节代码(.class文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。
演示类加载器的树状组织结构
public class ClassLoaderTree {
public static void main(String[] args) {
//获取加载该类的类加载器
ClassLoader loader = ClassLoaderTree.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
//获取该类加载器的父加载器
loader = loader.getParent();
}
}
}
打印结果为:
sun.misc.Launcher$AppClassLoader@addbf1
sun.misc.Launcher$ExtClassLoader@42e816
类加载器的委托机制
每个类加载器加载类时,又先委托给其上级类加载器。
方法 |
说明 |
getParent() |
返回该类加载器的父类加载器。 |
loadClass(String name) |
加载名称为name的类,返回的结果是java.lang.Class类的实例。 |
findClass(String name) |
查找名称为name的类,返回的结果是java.lang.Class类的实例。 |
findLoadedClass(String name) |
查找名称为name的已经被加载过的类,返回的结果是java.lang.Class类的实例。 |
defineClass(String name, byte[] b, int off, int len) |
把字节数组b中的内容转换成 Java类,返回的结果是 java.lang.Class类的实例。这个方法被声明为final的。 |
resolveClass(Class<?> c) |
链接指定的 Java类。 |
【编写自己的类加载器】
创建自定义加载器类
package cn.itcast.day2;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
//自定义加载器类必须继承ClassLoader
public class MyClassLoader extends ClassLoader{
//定义变量存储要加载的.Class文件所在目录
private String classDir;
//构造方法
public MyClassLoader(){
}
public MyClassLoader(String classDir){
this.classDir = classDir;
}
//主函数用于将指定.calss文件加密并存放到指定位置
public static void main(String[] args) {
//获取要加密的源
String srcPath = args[0];
//获取加密后文件存放的路径
String destDir = args[1];
//设置目的
String destPath = destDir + "\\"+ srcPath.substring(srcPath.lastIndexOf('\\')+1);
//创建输入流和输出流对象
FileInputStream fis = null;
FileOutputStream fos = null;
try{
fis = new FileInputStream(srcPath);
fos = new FileOutputStream(destPath);
//调用加密方法
cepher(fis,fos);
}catch(IOException e){
throw new RuntimeException();
}finally{
try{
if(fos != null)
fos.close();
}catch(IOException e){
e.printStackTrace();
}
try{
if(fis != null)
fis.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
//定义加密解密方法
public static void cepher(InputStream ips,OutputStream ops){
int b = -1;
try{
while((b = ips.read())!= -1){
ops.write(b ^ 0xff);
}
}catch(IOException e){
throw new RuntimeException("加密失败!");
}finally{
try{
if(ops != null)
ops.close();
}catch(IOException e){
e.printStackTrace();
}
try{
if(ips != null)
ips.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
@Override
//覆盖findClass方法,只让本加载器加载
protected Class<?> findClass(String arg0) throws ClassNotFoundException {
System.out.println(arg0);
//获取指定位置的.class文件
String classFileName = classDir + "\\" + arg0.substring(arg0.lastIndexOf('.')+1) + ".class";
//创建输入流,字符数组输出流
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
//将.class文件进行解密,并返回解密后的.class文件
try{
fis = new FileInputStream(classFileName);
bos = new ByteArrayOutputStream();
//解密
cepher(fis,bos);
byte[] bytes = bos.toByteArray();
//defineClass()方法将字符数组转换为.class文件
return defineClass(bytes, 0, bytes.length);
}catch(IOException e){
throw new RuntimeException();
}finally{
try{
if(bos != null)
bos.close();
}catch(IOException e){
e.printStackTrace();
}
try{
if(fis != null)
fis.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
创建类,并用MyClassLoader进行加密
package cn.itcast.day2;
import java.util.Date;
public class ClassLoaderAtt extends Date {
public String toString(){
return "hello java";
}
}
运行MyClassLoader参数为E:\test\javaenhance\bin\cn\itcast\day2\ClassLoaderAtt.class
itcastlib(该目录是相对路径)
运行完程序,会在itcastlib目录中生成加密的ClassLoaderAttachment.class,然后删除E:\test\javaenhance\bin\cn\itcast\day2目录中的ClassLoaderAttachment.class,因为不删除的话自定义加载器的loadClass方法会把此目录下的ClassLoaderAttachment.class加载,而不是调用findClass方法查找被自定义加载器加密的ClassLoaderAttachment.class
测试类
package cn.itcast.day2;
import java.util.Date;
public class ClassLoaderTest {
public static void main(String[] args) {
try {
//用自定义加载器加载.class文件
Class clazz = new MyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAtt");
//实例化对象
Date d = (Date)clazz.newInstance();
System.out.println(d);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
相关文章
- 暂无相关文章
用户点评