In my lastblog entry I explained how proxy based mock frameworks work and created my own
demo mock framework based on CGLIB. Now I will explain how exactly the CGLIB proxy
works. Because then you will understand why these things doesn't work with a
proxy:
- intercept static method calls
- intercept private method calls
- intercept final method calls
- build a proxy for a final class
ASM
CGLIB is
based on ASM. ASM is a library to create class files, on bytecode level, on the
fly. So it's very low level and you need a good understanding of the bytecode
to use it. But it abstracts the bytecode and is much more comfortable to generate
bytecode with ASM than writing the bytecode itself. Because it takes care of
the common structures like classes, constructors, method definitions and so on.
One of the most helpful features is that it takes care about the constant pool.
Because the constant pool holds many elements and you need to adapt it if you
change anything. E.g. if a new method is added than you have to add the needed
elements to the constant pool and increase the constant pool size. Or the
labels in ASM are quite nice, too. Or that there are constants for the opcodes.
After the complete class is generated, you have the bytecode of the class. This
bytecode is passed into the ClassLoader which will load the class and then the
class can be used.
How the generated CGLIB looks
Now you
know how the generation of the proxy works. The question is how the
generated proxy looks like. Actually it's quite simple. The proxy class extends
the original class. All classes which should be intercepted by the proxy will
be overridden. These methods will call the MethodInterceptor:: intercept method
with the corresponding parameters. If the proxy callback is null than the super
method will be called. Here is the code snippet for a simple echo(String)
method:
public class at.rseiler.concept.mock.Foo$$EnhancerByCGLIB$$c0699eacextends at.rseiler.concept.mock.Fooimplements org.mockito.cglib.proxy.Factory{
private static final org.mockito.cglib.proxy.MethodProxy CGLIB$echo$1$Proxy;private static final java.lang.reflect.Method CGLIB$echo$1$Method;// ...private org.mockito.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;// ...
public final String echo(String arg0) {if(CGLIB$CALLBACK_0 == null) {CGLIB$BIND_CALLBACKS(this);}
if(CGLIB$CALLBACK_0 != null) {// MethodInterceptor::intercept(Object obj, Method method, Object[] args, MethodProxy proxy)Object obj = CGLIB$CALLBACK_0.intercept(this, GLIB$echo$0$Method, new Object[] {arg0}, CGLIB$echo$0$Proxy);
if(!(obj instanceOf String)) {throw new ClassCastException();}
return obj;}
return super.echo(arg0);}
private static final void CGLIB$BIND_CALLBACKS(java.lang.Object object) {/* compiled code */}
// ...
}
Now you
should understand the limits of the proxy (see above). The limits caused
because the proxy is a subclass of the original class. Therefore it's not
possible to extend a final class or final methods and so on. That's just basic Java
limitations.
With code generation it's not possible to work around these limits. Sure it would be possible to generate a proxy class without the relationship to the original class. Than it would be possible to copy the whole class and insert the MethodInterceptor::intercept calls. This new class could remove all final keywords and make private methods public. The problem is that you can't call any method of this class without reflection. Because you don't have the type information of the "proxy" class at compile time - clearly because the class is generated at runtime. Further you can't pass the "proxy" object to any constructor or any method because it's not a subclass.
With code generation it's not possible to work around these limits. Sure it would be possible to generate a proxy class without the relationship to the original class. Than it would be possible to copy the whole class and insert the MethodInterceptor::intercept calls. This new class could remove all final keywords and make private methods public. The problem is that you can't call any method of this class without reflection. Because you don't have the type information of the "proxy" class at compile time - clearly because the class is generated at runtime. Further you can't pass the "proxy" object to any constructor or any method because it's not a subclass.
The only
way to break this limits is to do bytecode transformations of the original
class before the ClassLoader loads the class. Before the class is loaded
replace all private keywords with public keywords and to remove all final
keywords. To do so you need to create your own ClassLoader which will performs the
bytecode transformation. I don't know the code of PowerMock, but it must work
like this.
At last the
with javap --verbose decompiled bytecode of the echo(String) method from which
I created the Java code above:
public final java.lang.String echo(java.lang.String);flags: ACC_PUBLIC, ACC_FINALCode:stack=7, locals=2, args_size=20: aload_01: getfield #37 // Field CGLIB$CALLBACK_0:Lorg/mockito/cglib/proxy/MethodInterceptor;4: dup5: ifnonnull 178: pop9: aload_010: invokestatic #41 // Method CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V13: aload_014: getfield #37 // Field CGLIB$CALLBACK_0:Lorg/mockito/cglib/proxy/MethodInterceptor;17: dup18: ifnull 4521: aload_022: getstatic #64 // Field CGLIB$echo$1$Method:Ljava/lang/reflect/Method;25: iconst_126: anewarray #66 // class java/lang/Object29: dup30: iconst_031: aload_132: aastore33: getstatic #68 // Field CGLIB$echo$1$Proxy:Lorg/mockito/cglib/proxy/MethodProxy;36: invokeinterface #53, 5 // InterfaceMethod org/mockito/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lorg/mockito/cglib/proxy/MethodProxy;)Ljava/lang/Object;41: checkcast #55 // class java/lang/String44: areturn45: aload_046: aload_147: invokespecial #62 // Method at/rseiler/concept/mock/Foo.echo:(Ljava/lang/String;)Ljava/lang/String;50: areturn
Danke fur die Information! This really helps with a project I'm working on... tightly integrated 3rd party library which was not built with any useful interfaces!
AntwortenLöschenGreat Article… I love to read your articles because your writing style is too good, its is very very helpful for all of us and I never get bored while reading your article because, they are becomes a more and more interesting from the starting lines until the end.
AntwortenLöschenrpa training in bangalore
best rpa training in bangalore
RPA training in bangalore
RPA courses in bangalore
AntwortenLöschenVery nice post here and thanks for it .I always like and such a super contents of these post.
Excellent and very cool idea and great content of different kinds of the valuable information's.
Java training in Chennai
Java training in Bangalore
Java online training
Java training in Pune
I appreciate your efforts because it conveys the message of what you are trying to say. It's a great skill to make even the person who doesn't know about the subject could able to understand the subject . Your blogs are understandable and also elaborately described. I hope to read more and more interesting articles from your blog. All the best.
AntwortenLöschenpython Online training in chennai
python Online training in bangalore
python interview question and answers
Hmm, it seems like your site ate my first comment (it was extremely long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog. I as well as an aspiring blog writer, but I’m still new to the whole thing. Do you have any recommendations for newbie blog writers? I’d appreciate it.
AntwortenLöschenAWS Training in Bangalore with Placements | AWS Training in Bangalore Cost
AWS Training in Pune With Placement | AWS Devops Training in Pune
AWS Online Training | AWS Online Training Cost
AWS Training in Bangalore cost| Aws training in Bangalore Besant Technologies
A week ago, I had nothing to do and went to this site whole real cash online casino and decided to take a risk. We only live once to play in a casino. And did not regret
AntwortenLöschenNice post. Thanks for sharing this post with us.
AntwortenLöschenSpoken English Classes in Chennai
Best Spoken English Classes in Chennai
IELTS Coaching in Chennai
IELTS Coaching Centre in Chennai
English Speaking Classes in Mumbai
English Speaking Course in Mumbai
IELTS Classes in Mumbai
IELTS Coaching in Mumbai
IELTS Coaching in Anna Nagar
Spoken English Class in Anna Nagar
Dieser Kommentar wurde vom Autor entfernt.
AntwortenLöschenAfter signing up, you can hit the "Teaching" button. The "Create a course" button will show up that you can press to create a course and become a tutor. cursos de ti online
AntwortenLöschenIts very nice information in your blog content.
AntwortenLöschenPython Training in Chennai | Certification | Online Training Course | Python Training in Bangalore | Certification | Online Training Course | Python Training in Hyderabad | Certification | Online Training Course | Python Training in Coimbatore | Certification | Online Training Course | Python Training in Online | Python Certification Training Course
I found some useful information. share your more information .
AntwortenLöschenPython Training in Chennai | Certification | Online Training Course | Python Training in Bangalore | Certification | Online Training Course | Python Training in Hyderabad | Certification | Online Training Course | Python Training in Coimbatore | Certification | Online Training Course | Python Training in Online | Python Certification Training Course
Dieser Kommentar wurde vom Autor entfernt.
AntwortenLöschenThis blog is really impressive. i like it.
AntwortenLöschenIELTS training in chennai
German Classes in Chennai
GRE Coaching Classes in Chennai
TOEFL Coaching in Chennai
spoken english classes in chennai | Communication training
Great blog. All posts have something to learn. Your work is very good and i appreciate you and hopping for some more informative posts.
AntwortenLöschenWeb Designing Training in Chennai
Web Designing Course in Chennai
Web Designing Training in Bangalore
Web Designing Course in Bangalore
Web Designing Training in Hyderabad
Web Designing Course in Hyderabad
Web Designing Training in Coimbatore
Web Designing Training
Web Designing Online Training
This great article has really peaked my interest. I am going to book mark your blog and keep checking for new information about once per week.
AntwortenLöschenWeb Designing Training in Chennai
Web Designing Course in Chennai
Web Designing Training in Bangalore
Web Designing Course in Bangalore
Web Designing Training in Hyderabad
Web Designing Course in Hyderabad
Web Designing Training in Coimbatore
Web Designing Training
Web Designing Online Training
Your blog is really nice and informative. Thanks for sharing this post. oracle training in chennai
AntwortenLöschenReally nice and interesting post. I was looking for this kind of information and enjoyed reading this one. Keep posting. Thanks for sharing.
AntwortenLöschenangular js training in chennai
angular js training in tambaram
full stack training in chennai
full stack training in tambaram
php training in chennai
php training in tambaram
photoshop training in chennai
photoshop training in tambaram
Very nice post here and thanks for it .I always like and such a super contents of these post.
AntwortenLöschenhardware and networking training in chennai
hardware and networking training in omr
xamarin training in chennai
xamarin training in omr
ios training in chennai
ios training in omr
iot training in chennai
iot training in omr
This information is impressive..I am inspired with your post writing style & how continuously you describe this topic.
AntwortenLöschenData Science Training In Bangalore
career towards a sky-high with Infycle Technologies. Infycle Technologies provides the top Oracle DBA Training in Chennai and offering programs in Oracle such as Oracle PL/SQL, Oracle Programming, etc., in the 200% hands-on practical training with professional specialists in the field. In addition to that, the interviews will be arranged for the candidates to set their careers without any struggle. Of all that, Cen percent placement assurance will be given here. To learn Oracle DBA for making the best job for your life, call 7502633633 to Infycle Technologies and grab a free demo to know moreNo.1 Oracle DBA Training in Chennai | Infycle Technologies
AntwortenLöschenMuch thanks to you! A particularly great article and I gain so much of data from your blog. I'm waiting for more special thoughts from your blog...
AntwortenLöschenData Science Training in Hyderabad
Thanks for posting the best information and the blog is very helpful.
AntwortenLöschenAWS Training in bangalore | AWS Online Training
Python Training in Bangalore | Python Online Training
Artificial Intelligence Training in Bangalore | Artificial Intelligence Online Training
Bandicam Keygen is an awesome instrument causes you to enact the full premium highlights of Bandicam most recent form in zero of expense. Bandicam Registered Free
AntwortenLöschenUsers CoffeeCup Responsive Site Designer Serial Key with interactive effects and transitions. These techniques take your website Coffeecup Web Form Builder
AntwortenLöschen
AntwortenLöschenRomantic Christmas Wishes ... The best Christmas is the one when you're with me all day and all night. Spending time with you is my wish for this season. Merry. Christmas Message To A Loved One