<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    VIRGIN FOREST OF JAVA
    不要埋頭苦干,要學習,學習,再學習。。。。。
    powered by R.Zeus

    The Pitfalls of Dynamic Proxy Serialization

    Created by Caleb Powell. Last edited by Caleb Powell, 195 days ago.

    Recently, we ran into problems de-serializing proxy objects. The first pitfall involved a bug in Weblogic that prevented us from de-serializing a java.lang.reflect.Proxy instance. The second pitfall occurred as a result of using a Cglib proxy. In our efforts to deal with these pitfalls we deepened our understanding of how these libraries create dynamic proxies.

    Pitfall #1: Classloader Problems

    We wanted to use the java.lang.reflect.Proxy class to make instances of one (very simple) class assignable to different types of interfaces. Everything was going just swimingly and we were close to checking in our code. When it came time to run our integration tests, Weblogic began throwing a ClassNotFoundException whenever it attempted to de-serialize a proxy instance in a MessageDrivenBean. Once we confirmed that the interfaces were indeed on the Classpath, we fired up the debugger and dug a little deeper (but not until we consumed a a copious amount of Coca-Cola and Marlboros... thanks for the tip Mike). We discovered that - in the process of de-serializing our proxy object - the java.io.ObjectInputStream was trying to load our interfaces with the wrong classloader. It was using the parent of the Weblogic application classloader which had no knowledge of the classpath in our EAR file. We were were pretty certain that the reason was due to a bug in the way Weblogic was managing classloaders in it's JMS implementation (of course, Weblogic is not open source so we can't be 100% certain of this).

    We couldn't de-serialize the object ourselves inside the message bean and we couldn't modify the way Weblogic managed classloaders, so we tried using the Cglib library instead. The Cglib proxy worked? The reason is because the ObjectInputStream de-serializes Cglib instances differently than it does a java.lang.reflect.Proxy instance. Why? Because of a key difference between the two types of proxy objects;

    • When you create an instance using the JDK Proxy, it generates a subclass of the java.lang.reflect.Proxy class for you (the subclass is assignable to any interfaces you provide). Furthermore, the class generated by the java.lang.reflect.Proxy will have a different class descriptor (in fact, a Proxy class descriptor).
    • On the other hand, the Cglib library generates a subclass of an arbitrary class that you provide (as with the JDK proxy, the Cglib generated subclass will also be assignable to any interfaces you choose to provide). The class generated by the Cglib library will have a regular class descriptor.

    Whenever the ObjectInputStream de-serializes an object, it peeks at the Class descriptor. If it has a Proxy class descriptor, it invokes the ObjectInputStream.resolveProxyClass() method which creates a new version of the proxy subclass in the JVM (if it didn't already exist) based on the declared interfaces. Because the Cglib class has a normal class descriptor, the ObjectInputStream.resolveClass() method is invoked instead. For reasons we're not sure of, the classloader that is retrieved in the ObjectInputStream.resolveClass() method is the correct one and can resolve our interfaces/classes.

    Pitfall #2: Generated Subclasses

    Now our Cglib proxy was being de-serialized correctly when sent to a JMS MessageDrivenBean. But we we were also sending these proxies to a rich client, and the Cglib proxies were not being de-serialized there. We were stunned, but only temporarily. This result was to be expected. The Cglib generated objects were instances of a subclass generated dynamically on a different JVM. Our rich client JVM didn't recognize the class and was quite justified in throwing a ClassNotFoundException.

    It turns out there is a pretty simple solution to this problem. Basically, you need to implement the writeReplace() and readResolve() methods on the object that your proxy delegates methods to. The delegate uses these methods to de-proxy and re-proxy itself depending on whether it is being serialized or de-serialized. In our case, our delegate object is the super-class of our Proxy instance, so we implemented the writeReplace() and readResolve() methods on it. Here is an example using a class called DataHandler;

    public static class DataHandler implements Serializable {
    private static final long serialVersionUID = 1L;
    private final String someData;

    public DataHandler(String someData){
    this.someData = someData;
    }
    public String getSomeData() {
    return someData;
    }

    public boolean equals(Object obj) {
    return obj instanceof DataHandler ?
    ((DataHandler)obj).getSomeData().equals(this.someData)
    : false;
    }

    public Object writeReplace() throws ObjectStreamException{
    return new DataHandler(this.someData);
    }
    public Object readResolve() throws ObjectStreamException{
    return ProxyFactory.createCglibProxy(DataHandler.class, new Class[]{IFoo.class}, new Object[] {this.someData});
    }
    }

    public interface IFoo extends java.io.Serializable{
    }
    We create a proxy with the Cglib library like so;
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(DataHandler.class);
    enhancer.setInterfaces(new Class[]{IFoo.class});
    enhancer.setCallback(new NoOpCallback());//a NoOp callback. All methods will be invoked on the superclass

    //generates a subclass of DataHandler that is assignable to the IFoo interface.
    IFoo foo = (IFoo) enhancer.create(new Class[]{String.class}, new Object[] {"someData"});
    When the foo instance is serialized, the super-class (DataHandler) method writeReplace() is invoked. The writeReplace method returns a new instance of the DataHandler class, thereby discarding the Proxy wrapper subclass. It's this new instance of DataHandler that gets serialized, not the original subclass. When the DataHandler instance is eventually de-serialized, the readResolve() method is invoked on it. The readResolve() will generate and return a new proxy subclass equivalent to the original. We learned this little trick by studying the code in the Hibernate project which uses Cglib for proxies and is open-source.



    posted on 2008-08-25 13:29 R.Zeus 閱讀(297) 評論(0)  編輯  收藏 所屬分類: ReflectionCGLIB
    主站蜘蛛池模板: 一级毛片直播亚洲| 猫咪免费人成网站在线观看| 国产免费资源高清小视频在线观看| 亚洲制服在线观看| 国产va免费精品观看精品| 亚洲人成www在线播放| 免费毛片在线看片免费丝瓜视频| 456亚洲人成在线播放网站| 久久不见久久见免费影院| 亚洲熟妇av午夜无码不卡| 日本免费一本天堂在线| 免费很黄无遮挡的视频毛片| 亚洲伊人久久综合中文成人网| 91av免费在线视频| 日韩亚洲AV无码一区二区不卡| 59pao成国产成视频永久免费 | 成人五级毛片免费播放| 国产精品亚洲综合一区在线观看| 亚洲国产一成久久精品国产成人综合| 中文字幕免费在线看线人动作大片| 国产精品亚洲片在线观看不卡| 四虎在线视频免费观看视频| 在线综合亚洲中文精品| 亚洲国产精品13p| 久久青草免费91观看| 亚洲性线免费观看视频成熟| 免费一级毛片正在播放| 免费无码又爽又刺激高潮软件| 亚洲美女视频免费| 国产精品成人四虎免费视频| 中国人免费观看高清在线观看二区| 亚洲视频一区网站| 免费久久精品国产片香蕉| 黄色网址在线免费| 亚洲精品国产综合久久久久紧| 久久国产成人精品国产成人亚洲| 亚洲精品免费视频| 国产精品久久亚洲一区二区| 香蕉视频在线观看亚洲| 国产免费私拍一区二区三区| 久久午夜夜伦鲁鲁片无码免费|