自定义ClassLoader遇到的问题

1.自定义的类加载器


package classloader;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
/**
* 加载类----->定义类------>解析类
* loadClass---->defineClass ------>resolveClass
*/
class MyClassLoader extends ClassLoader {

public static void main(String[] args)throws Exception{

ClassLoader loader = new MyClassLoader();
Class clazz = loader.loadClass("classloader.Pig");
Object pig = clazz.newInstance();
System.out.println(pig.toString());
System.out.println(clazz.getClassLoader());
System.out.println(pig);
}

public MyClassLoader(){
}

/* 类加载器
* resolve:参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。如果 JVM 只需要知道该类是否存在或找出该类的超类,那么就不需要解析。
*/
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) {
//它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象
//核心:使用的ClassLoader是系统默认的:sun.misc.Launcher$AppClassLoader@131f71a
clas = findSystemClass( name );
}

if(clas == null){

throw new ClassNotFoundException("该类不存在");
}

//是否需要解析该类
if (resolve && clas != null)
resolveClass( clas );
return clas;
}

//构造该类的Class对象
public Class findClass(String name){

try{
byte[] b = loadClassBytes();
if(b == null){
return null;
}
return defineClass("classloader.Pig", b, 0, b.length);

}catch(Exception e){
System.out.print(e.getMessage());
}
return null;
}
/**
* 加载编译后字节码文件的数据
*/
private byte[] loadClassBytes() throws ClassNotFoundException {
try {
String classFile = "c:/temp/Pig.class";
FileInputStream fis = new FileInputStream(classFile);
FileChannel fileC = fis.getChannel();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableByteChannel outC = Channels.newChannel(baos);
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
while (true) {
int i = fileC.read(buffer);
if (i == 0 || i == -1) {
break;
}
buffer.flip();
outC.write(buffer);
buffer.clear();
}
fis.close();
return baos.toByteArray();
} catch (IOException fnfe) {
throw new ClassNotFoundException(className);
}
}

}

2.Pig类的代码如下:

package classloader;

public class Pig {

public static void main(String[] args){
System.out.println("OK");
}
}


[color=red]Pig.class文件拷贝到c:/temp目录下。[/color]

出现的问题:在自定义的MyClassLoader中return defineClass("classloader.Pig", b, 0, b.length);报异常:

Exception in thread "main" java.lang.ClassCircularityError: classloader/Pig
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at classloader.MyClassLoader.findClass(MyClassLoader.java:69)
at classloader.MyClassLoader.loadClass(MyClassLoader.java:40)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.lang.ClassLoader.defineClass(Unknown Source)
at classloader.MyClassLoader.findClass(MyClassLoader.java:69)
at classloader.MyClassLoader.loadClass(MyClassLoader.java:40)
at java.lang.ClassLoader.loadClass(Unknown Source)
at classloader.MyClassLoader.main(MyClassLoader.java:19)


[color=red]如果Pig.java不带包名(即去掉:package classloader;)。然后MyClassLoader里相应的包名也都去掉。就完全没问题。[/color]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值