类加载及执行子系统的案例与实战

  在class文件格式与执行引擎这部分中,用的程序能直接影响的内容并不太多,class文件以何种格式存储,类型何时加载,如何连接,以及虚拟机如何执行字节码指令都是由虚拟机直接控制的行为,用户程序无法对其进行改变。能通过程序进行操作的,主要是字节码生成与类加载器这两部分功能。

一。Tomcat:正统的类加载架构

   主流的java web服务器,如Tomcat,Jetty,WebLogic,WebSphere等的服务器,都实现了自己定义的类加载器,因为一个健全的Web服务器,要解决以下几个问题:

    1.部署在同一个服务器上的两个Web应用程序所使用的java类库可以实现相互隔离

     2.部署在同一个服务器上的两个Web应用程序所使用的java类库可以相互共享。

     3.服务器需要尽可能地保证 自身的安全不受部署Web应用程序影响 。

     4.支持JSP应用的Web服务器,大多数都需要支持HotSwap功能。 

    在Tomcat目录结构中,有3组目录(“/common/*”,"/server/*"和“/shared/*”)可以存放在java类库,另外还可以加上Web应用程序自身的目录“WEB-INF/*”,一共4组,把java类库位置在这些目录中含义分别如下

/common/类可被Tomcat和所有Web应用程序共同使用
/server/类可被Tomcat使用,对所有的Web应用程序都不可见
/share/类库可被所有的Web应用程序共同使用,但对Tomcat自己不可见
/WebApp/WEB-INF仅仅可以被此Web应用程序使用,对Tomcat和其他Web应用程序都不可见

从以上图中看得出来,Tomcat使用的是双亲委派模型来实现的

二。OSGI灵活的类加载器架构

所以上图中的类加载器没有指明具体的加载器实现,只是一个体现了加载器之间关系的概念模型,并且只是体现了OSGi中最简单的加载器委派关系。一般来说,在OSGi中,加载一个类可能发生的查找行为和委派关系会比上图中显示的复杂,类加载时的查找规则如下:

    1)以java.*开头的类,委派给父类加载器加载

    2)否则,委派列表名单内的类,委派给父类加载器加载

    3)否则,Import列表中的类,委派给Export这个类的Bundle的类加载器加载

    4)否则,查找当前Bundle的ClassPath,使用自己的类加载器加载

    5)否则,查找是否在自己的Fragment Bundle中,如果是,则委派给Fragment bundle的类加载器加载

    6)否则,查找Dynamic Import列表的Bundle,委派给对应Bundle的类加载器加载

    7)否则,查找失败

  从之前的图可以看出,在OSGi里面,加载器的关系不再是双亲委派模型的树形架构,而是已经进一步发展成了一种更复杂的、运行时才能确定的网状结构。

三。字节码生成技术与动态代理的实现

     字节码生成并不是什么高深的技术,看到这个标题也先不必去想诸如Javassist,CGLib,ASM之类的字节码类,因为JDK里面的javac命令就是字节码生成技术“老祖宗”,并且javac也是一个由java程序写成的程序,要深入了解字节码生成,阅读javac的源码是个很好的途径,不过javac对于我们这个例子来说太过庞大了。

      动态代理中所谓的动态,是针对使用Java代码实际编写了代理类的静态代理而言,它的优势不在于省去了代理行为,当代理类与原始类脱离直接联系后,就可以很灵活重用不同的应用场景之中。 以下实现最简单的动态代理的用法

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestPoxy {
    interface  IHello{
        void sayHello();
    }
    static class Hello implements IHello{
        public void sayHello(){
            System.out.println("hello world");
        }

    }
    static class DynamicProxy implements InvocationHandler{
        Object orignalObj;
        Object bind(Object originalObj){
            this.orignalObj= originalObj;
            return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),originalObj.getClass().getInterfaces(),this);
        }
        public Object invoke(Object proxy, Method method,Object[] args)throws Throwable{
            System.out.println("welcome");
            return method.invoke(orignalObj,args);
        }
    }
    public static void main(String[] args){
        IHello hello = (IHello) new DynamicProxy().bind(new Hello());
        hello.sayHello();
    }
}

三。Retrotranslator:跨越JDK版本 

     学习http://retrotranslator.sourceforge.net/这篇文章

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值