0%

JVM之第九章:类加载及执行子系统的案例与实战

第九章:类加载及执行子系统的案例与实战

在Class文件以何种方式存储,类型何时加载,如何连接,以及虚拟机如何执行字节码指令等都是虚拟机直接控制的行为,用户程序无法进行改变,能通过程序进行操作的,主要是字节码生成与类加载器两部分的功能。

案例分析

Tomcat:正统的类加载器架构

在Tomcat目录结构中有三组目录可以放Java类库,另外再加上Web应用程序自身的目录

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

Tomcat自定义了多个类加载器,并且按照经典的双亲委派模型来实现

  • CommonCLassLoader->/common/*
  • CatalinaClassLoader->/server/*
  • SharedClassLoader->/shared/*
  • WebappClassLoader->/WebApp/WEB-INF/*,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器
字节码生成技术和动态代理实现
public class DynamicProxyTest {

    interface IHello {
        void sayHello();
    }

    static class Hello implements IHello {

        @Override
        public void sayHello() {
            System.out.println("hello world");
        }
    }

    public static class GoodBye implements IHello {

        @Override
        public void sayHello() {
            System.out.println("say goodBye");
        }
    }

    static class DynamicProxy<T> implements InvocationHandler {
        T originalObj;

        T bind(T originalObj) {
            this.originalObj = originalObj;
            return (T) Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),
                    originalObj.getClass().getInterfaces(),
                    this);
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("welcome");
            return method.invoke(originalObj, args);
        }

        public static void main(String[] args) {
            IHello hello = new DynamicProxy<IHello>().bind(new Hello());
            hello.sayHello();
            IHello hello2 = new DynamicProxy<IHello>().bind(new GoodBye());
            hello2.sayHello();
        }
    }
}
~~