`
nanapoleon
  • 浏览: 46873 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

ClassLoader学习记录2

阅读更多
    写程序的时候,时常会思考,我们的类是哪来的?为何我们想用sdk中的类,就有这个类呢?答案肯定是classloader读进虚拟机来的。那他究竟是怎么被加载到虚拟机中的呢?看看如何定制classloader的代码,就相当一目了然了。
main() {
    runClass(name, key);
}

public void runClass(String name, int key){
    ClassLoader classLoader = new CryptoClassLoader(key);
    Class<?> c = classLoader.loadClass();
    Method m = c.getMethod("main", String[].class);
    m.invoke(null, (Object)new String[]{});
}

class CryptoClassLoader extends ClassLoader{
    int key;

    CryptoClassLoader(int key){
        this.key = key
    }

    protected Class<?> findClass(String name) throws ClassNotFoundException{
        byte[] classBytes = null;
        try{
            classBytes = loadClassBytes(name);
        } catch(IOException e) {
            throw new ClassNotFoundException();
        }
        
        Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
        if (cl == null) throw new ClassNotFoundException(name);
        return cl;
    }

    private byte[] loadClassBytes(String name) throws IOException{
        String cname = name.replace(".","/") + ".caesar"; //(我怎么觉得应该是.class? 不太懂这里...不会印刷错误吧?)
        FileInputStream in = null;
        in = new FileInputStream(cname);
        try{
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int ch;
            while((ch = in.read()) != -1){
                byte b = (byte)(ch - key);
                buffer.write(b);
            }    
            return b.toByteArray();
        } finally {
            in.close(); 
        }    
    }
}

    此段代码看完发现(defineClass方法),虚拟机加载新类的方式就是:使用父类的defineClass方法将某Class类的字节码传递给虚拟机,(其实就是以字节形式把字节码传递给虚拟机),并且创建相应的类。
    下来解释一下上面的程序:key这个int。这个例子使用了一个小的加密方法,就是类文件中所有的字节都向后移动了key个位置,比如3,那么,在加载此类时,就应该向前移动3,来保证文件被解密。这里我们就引申出了自定义classloader的用法之一,即加密。你想使用这个类?请知道密钥先!就好像游戏的注册码一样,没有key和我们的classloader,你拿到类文件也是没有任何意义的。(好吧我承认程序里的加密方法不怎么先进)
    怎么样,很棒吧。其实一直以来,还有个疑问,如果包名和类名一样的情况,classloader应该如何处理?首先,像上面的情况,一个路径下是不能放相同名字的类文件的,先排除此情况。那如果在多jar包的环境下,真的有两个一样的类名呢?我想、估计是直接使用第一个被load进的类吧,因为classloader会判断此类已经被加载进来了,毕竟classloader也不会读心数,知道你想使用哪个jar包的类。
    其实,如果类名和包名都重复,我们可以看见,如果classloader不一样,你那么也不会有任何问题,它们之间是不会相互干扰的,比如Web中的每个applet,就是由不同的classloader加载的,所以,命名冲突在applet之间是允许的。就好像不同的命名空间
    还有个比喻,我想到的,可能会比较烂。比如,android上的两个不同的apk,如果两个程序中,使用相同的包名和类名的话,应该也不会相互干扰,因为不同的classloader导致。(因为每个进程都有自己的虚拟机,那么classloader也理应不同,恩,应该是这样,本身classloader就是给虚拟机服务的嘛。)
   
   
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics