锘??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品国产免费,亚洲国产综合91精品麻豆,亚洲国产成人久久一区久久http://www.tkk7.com/RR00/category/34077.html涓嶈鍩嬪ご鑻﹀共錛岃瀛︿範錛屽涔狅紝鍐嶅涔犮傘傘傘傘? <br> powered by <font color='orange'>R.Zeus</font>zh-cnMon, 25 Aug 2008 08:44:39 GMTMon, 25 Aug 2008 08:44:39 GMT60The Pitfalls of Dynamic Proxy Serializationhttp://www.tkk7.com/RR00/articles/224132.htmlR.ZeusR.ZeusMon, 25 Aug 2008 05:29:00 GMThttp://www.tkk7.com/RR00/articles/224132.htmlhttp://www.tkk7.com/RR00/comments/224132.htmlhttp://www.tkk7.com/RR00/articles/224132.html#Feedback0http://www.tkk7.com/RR00/comments/commentRss/224132.htmlhttp://www.tkk7.com/RR00/services/trackbacks/224132.html

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.





R.Zeus 2008-08-25 13:29 鍙戣〃璇勮
]]>
主站蜘蛛池模板: 日韩免费视频网站| 免费高清在线影片一区| 亚洲熟妇av一区二区三区 | 亚洲日本乱码一区二区在线二产线| 精品国产免费一区二区三区| 久久久久亚洲AV成人网| 国产黄片不卡免费| 亚洲AV日韩AV永久无码下载| 1000部拍拍拍18勿入免费视频下载 | 亚洲国产精品狼友中文久久久| 成人精品综合免费视频| 国产性爱在线观看亚洲黄色一级片| 久久不见久久见免费影院www日本 久久WWW免费人成—看片 | 亚洲精品无码成人| 一本久到久久亚洲综合| 日本免费xxxx| 亚洲一级毛片免费观看| 青青青国产免费一夜七次郎| 免费在线观看自拍性爱视频| 亚洲女久久久噜噜噜熟女| 无码一区二区三区免费| 67194在线午夜亚洲| 日本一区二区三区日本免费| 国产黄在线播放免费观看| 亚洲第一精品福利| 成人免费午夜在线观看| 无遮挡呻吟娇喘视频免费播放| 亚洲精品无码久久久久sm| 2020久久精品国产免费| 免费无码婬片aaa直播表情| 亚洲AV人无码综合在线观看| 成人片黄网站色大片免费| jizz在线免费观看| 亚洲成人网在线观看| 波多野结衣中文一区二区免费| 99在线视频免费观看| 亚洲综合久久精品无码色欲| 在线精品亚洲一区二区小说| 性短视频在线观看免费不卡流畅| 国产亚洲精品美女久久久| 国产啪精品视频网免费|