I don't understand why PowerMock use javassist library and Mockito is not.
Most of the conversations about code generation libraries in Java circle around three libraries: cglib, javassist, and ByteBuddy. Mockito was formerly on cglib, but now uses ByteBuddy as its default code generator.
As ByteBuddy author Rafael Winterhalter notes here:
javassist offers an API for modifying classes and not only for subclassing them. These APIs allow also for byte code-level manipulation while cglib only allows for several hardcoded interceptions.
Though I am not a contributor on any of these mocking frameworks or libraries, it's worth noting that Powermock works in part by editing class implementations to intercept calls to private, static, and final methods and classes within compiled bytecode. This likely explains the requirement to use javassist from Powermock: cglib was not capable of editing existing classes. Mockito, in contrast, needs simpler code generation in order to generate a subclass of the given class; this is functionality that cglib and ByteBuddy were written to provide.
Note that open Powermock issue 727 tracks an incomplete migration of Powermock from Javassist to ByteBuddy.
Now, the reverse: Why doesn't Mockito switch to Javassist instead of ByteBuddy? Again, we don't have a direct answer, but the ByteBuddy tutorial expresses an opinion (under "General Information" for Javassist, emphasis mine):
This library comes with a compiler that takes strings containing Java source code which are translated into Java byte code during the runtime of an application. This is very ambitious and in principle a great idea since Java source code is obviously a great way for describing Java classes. However, the Javassist compiler does not compare to the javac compiler in its functionality and allows for easy mistakes when dynamically composing strings to implement more complex logic. Additionally, Javassist comes with a proxy library which is similar to the JCL's proxy utilities but allows extending classes and is not limited to interfaces. The scope of Javassist's proxy tools remain however equally limited in its API and functionality.
In short: There is anecdotal reason to doubt Javassist's safety/functionality/stability. Mockito did not require Javassist's features, so it could migrate straight from cglib to ByteBuddy. PowerMock did require Javassist's features, and the efforts to migrate PowerMock to ByteBuddy are stalled and ongoing.
Related
As I understand, the 2 frameworks are both static that injects monitor codes into class codes. So, what is the difference?
ASM is a framework/library which provides you an API to manipulate existing bytecode and/or generate new bytecode easily.
AspectJ, on the other hand is a language extension on top of the Java language with it's own syntax, specifically designed to extend the capabilities of the Java runtime with aspect oriented programming concepts. It includes a compiler/weaver, which can either be run at compile time or run-time.
They're similar in the sense that both achieve their goals by bytecode manipulation of existing bytecode and/or generating new bytecode.
ASM is more general in the sense that it doesn't have an opinion about how you would want to modify existing bytecode, it just gives you an API and you can do whatever you want with it. AspectJ, on the other hand, is more specific, more narrow scoped, it only supports a few predefined AOP constructs, but it gives you an interface (the aspectj language) which is much easier to work with if you can fit within those constructs it provides you with.
For most use-cases I've seen, AspectJ is more than enough, but in those rare cases where it wouldn't, ASM can be a good alternative, but you'll need more programming work to achieve similar results.
Cycript is a console based application that is a blend of Objective-C and JavaScript. Cycript is very useful for dynamic analysis of iOS applications.
If you write any methods or the complete ipa with Swift is it still possible to hook the application on a jailbroken device? Or is Swift safe like "native C" Code on iOS ?
I'm not really familiar with Cycript but I have a little understanding of the Swift compiler.
Swift code will be more resistant to hooking but it should not be completely impossible. NSObject subclasses and Swift classes that are declared #objc should be as accessible as Objective-C code. Pure Swift code, especially in optimised builds would be harder to inject code into because they are often statically dispatched and in many cases will actually be inlined into the calling code.
Where code hasn't been inlined it may may be possible to patch the functions in memory themselves to jump to an alternative function but it wouldn't be as easy as just modifying function tables.
Where key functions have been inlined it may be possible to find and modify each usage if common patterns of code that could be identified and if the function is long enough it may be posible to patch in a jump to an alternate version but this would get really quite tricky.
I'm currently writing an embedded application for J2ME environment (CLDC 1.1 configuration and IMP-NG profile). Being spoiled by all those new features in JVM-based languages (Groovy, Scala, Clojure, you name it), I was considering using one of them for my code.
However, most of the mentioned languages require pretty decent JVM environment. Most so-called "dynamic" languages require the VM to have reflection. Many ask for annotations support. None of the above features are available under J2ME.
From what I found, Xtend looks like a viable options, as its compiler spits out plain Java, not bytecode, and doesn't require any library for runtime needs. Of course, the generated Java code also must meet some requirements, but Xtend webpage looks promising in this regard:
Xtend just does classes and nothing else
Interface definitions in Java are already nice and concise. They have a decent default visibility and also in other areas there is very little to improve. Given all the knowledge and the great tools being able to handle these files there is no reason to define them in a different way. The same applies for enums and annotation types.
That's why Xtend can do classes only and relies on interfaces, annotations and enums being defined in Java. Xtend is really not meant to replace Java but to modernize it.
Am I right and it is possible to compile Xtend-generated code for J2ME platform, or there are some constructs that will not work there?
Alternatively, can you recommend any other "rich" Java modification language that can be run on J2ME?
Update: Knowing that the "compiler" producing results as another source code is called transcompiler, one can also find Mirah, a tool which requires no runtime library and specific Java features.
Xtend's generated code uses google guava heavily. If that is compatible to the J2ME, Xtend could be the language of your choice. I'm not aware of anything that prevents from using it on other platforms that provide a dedicated development kit (e.g. Android).
In addition to being able to generate Java source, Mirah recently added support for javac's --bootclasspath option, which allows you to generate your bytecode against a non-standard version of the java core classes, e.g. LeJOS.
It's still a little fresh, but it'd be nice to have more people using it on different javas.
There are some frameworks out there for dynamic bytecode generation, manipulation and weaving (BCEL, CGLIB, javassist, ASM, MPS). I want to learn about them, but since I don't have much time to know all the details about all of them, I would like to see a sort of comparison chart saying the advantages and disadvantages of one versus the others and an explanation of why.
Here in SO, I found a lot of questions asking something similar, and the answers normally said "you can use cglib or ASM", or "javassist is better than cglib", or "BCEL is old and is dying" or "ASM is the best because it gives X and Y". These answers are useful, but does not fully answer the question in the scope that I want, comparing them more deeply and giving the advantages and disadvantages of each one.
Analysis of bytecode libraries
As I can tell from the answers you got here and ones in the questions that you have looked at, these answers do not formally address the question in the explicit manner you have stated. You asked for a comparison, meanwhile these answers have vaguely stated what one might want based on what your target is (e.g. Do you need to know bytecode? [y/n]), or are too narrow.
This answer is a short analysis of each bytecode framework, and provides a quick comparison at the end.
Javassist
Tiny (javassist.jar (3.21.0) is ~707KB / javassist-rel_3_22_0_cr1.zip is ~1.5MB)
High(/Low)-level
Straightforward
Feature-complete
Requires minimal to no class file format knowledge
Requires moderate Java instruction set knowledge
Minimal learning effort
Has some quirks in the single-line/multi-line compile-and-insert-bytecode methods
I personally prefer Javassist simply because of how quickly you can get to using it and building and manipulating classes with it. The tutorial is straightforward and easy to follow. The jar file is a tiny 707KB, so it is nice and portable; makes it suitable for standalone applications.
ASM
Large (asm-6.0_ALPHA-bin.zip is ~2.9MB / asm-svn-latest.tar.gz (10/15/2016) is ~41MB)
Low(/High)-level
Comprehensive
Feature-complete
Recommend a proficient knowledge of class file format
Requires proficiency with Java instruction set
Moderate learning effort (somewhat complex)
ASM by ObjectWeb is a very comprehensive library which lacks nothing related to building, generating, and loading classes. In fact, it even has class analysis tools with predefined analyzers. It is said to be the industry standard for bytecode manipulation. It is also the reason why I steer clear away from it.
When I see examples of ASM, it seems like a cumbersome beast of a task with the number of lines it takes to modify or load a class. Even some of the parameters to some methods seem a bit cryptic and out of place for Java. With things like ACC_PUBLIC, and plenty of method calls with null everywhere, it honestly does look like it is better suited for a low-level language like C. Why not simply just pass a String literal like "public", or an enum Modifier.PUBLIC? It's more friendly and easy to use. That is my opinion, however.
For reference, here is an ASM (4.0) tutorial: https://www.javacodegeeks.com/2012/02/manipulating-java-class-files-with-asm.html
BCEL
Small (bcel-6.0-bin.zip is 7.3MB / bcel-6.0-src.zip is 1.4MB)
Low-level
Adequate
Gets the job done
Requires proficiency with Java instruction set
Easy to learn
From what I have seen, this library is your basic class library that lets you do everything you need to—if you can spare a few months or years.
Here is a BCEL tutorial that really spells it out: http://www.geekyarticles.com/2011/08/manipulating-java-class-files-with-bcel.html?m=1
cglib
Very tiny (cglib-3.2.5.jar is 295KB/source code)
Depends on ASM
High-level
Feature-complete (Bytecode Generation)
Little or no Java bytecode knowledge needed
Easy to learn
Esoteric Library
Despite the fact that you can read information from classes, and that you can transform classes, the library seems tailored to proxies. The tutorial is all about beans for the proxies, and it even mentions it is used by "data access frameworks to generate dynamic proxy objects and intercept field access." Still, I see no reason why you can't use it for the more simple purpose of bytecode manipulation instead of proxies.
ByteBuddy
Small bin/"Huge" src (by comparison) (byte-buddy-dep-1.8.12.jar is ~2.72 MB / 1.8.12 (zip) is 124.537 MB (exact))
Depends on ASM
High-level
Feature-complete
Personally, a peculiar name for a Service Pattern class (ByteBuddy.class)
Little or no Java byte code knowledge needed
Easy to learn
Long story short, where BCEL is lacking, ByteBuddy is abundant. It uses a primary class called ByteBuddy using the Service Design Pattern. You create a new instance of ByteBuddy, and this represents a class that you want to modify. When you are done with your modifications, you can then make a DynamicType with make().
On their website is a full tutorial with API documentation. The purpose seems to be for rather high-level modifications. When it comes to methods, there does not appear to be anything in the official tutorial, or any 3rd party tutorial, about creating a method from scratch, apart from delegating a method (EDITME if you know where this is explained).
Their tutorial can be found here on their website. Some examples can be found here.
Java Class Assistant (jCLA)
I have my own bytecode library that I am building, which will be called Java Class Assistant, or jCLA for short, because of another project I am working on and because of said quirks with Javassist, but I will not be releasing it to GitHub until it is finished but the project is currently available to browse on GitHub and give feedback on as it is currently in alpha, but still workable enough to be a basic class library (currently working on the compilers; please help me if you can! It will be released a lot sooner!).
It will be quite bare bones with the ability to read and write class files to and from a JAR file, as well as the ability to compile and decompile bytecode to and from source code and class files.
The overall usage pattern makes it rather easy to work with jCLA, though it may take some getting used to and is apparently quite similar to ByteBuddy in its style of methods and method parameters for class modifications:
import jcla.ClassPool;
import jcla.ClassBuilder;
import jcla.ClassDefinition;
import jcla.MethodBuilder;
import jcla.FieldBuilder;
import jcla.jar.JavaArchive;
import jcla.classfile.ClassFile;
import jcla.io.ClassFileOutputStream;
public class JCLADemo {
public static void main(String... args) {
// get the class pool for this JVM instance
ClassPool classes = ClassPool.getLocal();
// get a class that is loaded in the JVM
ClassDefinition classDefinition = classes.get("my.package.MyNumberPrinter");
// create a class builder to modify the class
ClassBuilder clMyNumberPrinter= new ClassBuilder(classDefinition);
// create a new method with name printNumber
MethodBuilder printNumber = new MethodBuilder("printNumber");
// add access modifiers (use modifiers() for convenience)
printNumber.modifier(Modifier.PUBLIC);
// set return type (void)
printNumber.returns("void");
// add a parameter (use parameters() for convenience)
printNumber.parameter("int", "number");
// set the body of the method (compiled to bytecode)
// use body(byte[]) or insert(byte[]) for bytecode
// insert(String) also compiles to bytecode
printNumber.body("System.out.println(\"the number is: \" + number\");");
// add the method to the class
// you can use method(MethodDefinition) or method(MethodBuilder)
clMyNumberPrinter.method(printNumber.build());
// add a field to the class
FieldBuilder HELLO = new FieldBuilder("HELLO");
// set the modifiers for hello; convenience method example
HELLO.modifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL);
// set the type of this field
HELLO.type("java.lang.String");
// set the actual value of this field
// this overloaded method expects a VariableInitializer production
HELLO.value("\"Hello from \" + getClass().getSimpleName() + \"!\"");
// add the field to the class (same overloads as clMyNumberPrinter.method())
clMyNumberPrinter.field(HELLO.build());
// redefine
classDefinition = clMyNumberPrinter.build();
// update the class definition in the JVM's ClassPool
// (this updates the actual JVM's loaded class)
classes.update(classDefinition);
// write to disk
JavaArchive archive = new JavaArchive("myjar.jar");
ClassFile classFile = new ClassFile(classDefinition);
ClassFileOutputStream stream = new ClassFileOutputStream(archive);
try {
stream.write(classFile);
} catch(IOException e) {
// print to System.out
} finally {
stream.close();
}
}
}
(VariableInitializer production specification for your convenience.)
As may be implied from the above snippet, each ClassDefinition is immutable. This makes jCLA more secure, thread-safe, network-safe, and easy to use. The system revolves primarily around ClassDefinitions as the object of choice for querying information about a class in a high-level manner, and the system is built in such a way that ClassDefinition is converted to and from target types such as ClassBuilder and ClassFile.
jCLA uses a tiered system for class data. At the bottom, you have the immutable ClassFile: a struct or software representation of a class file. Then you have immutable ClassDefinitions which are converted from ClassFiles into something less cryptic and more manageable and useful to the programmer who is modifying or reading data from the class, and is comparable to information accessed through java.lang.Class. Finally, you have mutable ClassBuilders. The ClassBuilder is how classes are modified or created. It allows that you can create a ClassDefinition directly from the builder from its current state. Creating a new builder for each class is not necessary as the reset() method will clear the variables.
(Analysis of this library will be available as soon as it is ready for release.)
But until then, as of today:
Small (src: 227.704 KB exact, 6/2/2018)
Self-sufficient (no dependencies except Java's shipped library)
High-level
No required knowledge of java bytecode or class files (for tier 1 API, e.g. ClassBuilder, ClassDefinition, etc.)
Easy to learn (even easier if coming from ByteBuddy)
I still recommend learning about java bytecode however. It will make debugging easier.
Comparison
Considering all of these analyses (excluding jCLA for now), the broadest framework is ASM, the easiest to use is Javassist, the most basic implementation is BCEL, and the most high-level for bytecode generation and proxies is cglib.
ByteBuddy deserves its own explanation. It is easy to use like Javassist, but appears to be lacking some of the features that make Javassist great, such as method creation from scratch, so you would need to use ASM for that apparently. If you need to do some lightweight modification with classes, ByteBuddy is the way to go, but for more advanced modification of classes while maintaining a high level of abstraction, Javassist is a better choice.
Note: if I missed a Library, please edit this answer or mention it in a comment.
If your interest in bytecode generation is only to use it, the comparison chart becomes rather simple :
Do you need to understand bytecode?
for javassist : no
for all others : yes
Of course, even with javassist you may be confronted with bytecode concepts at some point. Likewise, some of the other libraries (such as ASM) have a more high-level api and/or tool support to shield you from many of the bytecode details.
What really distinguishes javassist though, is the inclusion of a basic java compiler. This makes it very easy to write complex class transformations : you only have to put a java fragment in a String and use the library to insert it at specific points in the program. The included compiler will build the equivalent bytecode, which is then inserted into the existing classes.
First of all it all depends on your task. Do you want to generate the new code or analyze existing bytecode and how complex analysis you may need. Also how much time you want to invest into learning Java bytecode. You can break down bytecode framework into ones that provide a high level API, that allows you to get away from learning low level opcodes and JVM internals (e.g, javaassist and CGLIB) and low level frameworks when you need to understand JVM or use some bytecode generation tools (ASM and BCEL). For analyzis BCEL historically evolved a bit more, but ASM provides a decent functionality that is easy to extend. Also note, ASM is probably the only framework that provides the most advanced support for STACK_MAP information required by the new bytecode verifier enabled by default in Java 7.
I'm writing my master thesis, which deals with AOP in .NET, among other things, and I mention the lack of support for replacing classes at load time as an important factor in the fact that there are currently no .NET AOP frameworks that perform true dynamic weaving -- not without imposing the requirement that woven classes must extend ContextBoundObject or MarshalByRefObject or expose all their semantics on an interface.
You can however do this with Java in the JVM thanks to ClassFileTransformer:
You extend ClassFileTransformer.
You subscribe to the class load event.
On class load, you rewrite the class and replace it.
All this is very well, but my project director has asked me, quite in the last minute, to give him a list of frameworks (and associated languages) that do / do not support class replacement. I really have no time to look for this now: I wouldn't feel comfortable just doing a superficial research and potentially putting erroneous information in my thesis.
So I ask you, oh almighty programming community, can you help out? Of course, I'm not asking you to research this yourselves. Simply, if you know for sure that a particular framework supports / doesn't support this, leave it as an answer. If you're not sure please don't forget to point it out.
Thanks so much!
EDIT: #ewernli
I'm asking about (2).
In C# you can indeed emit code at run-time and create new classes dynamically, but they are new classes, they do not replace an existing class. What I'd like to do is to transform the class at load-time, like you can do in Java with the ClassFileTransformer.
About modifying a method's signature: yes, you're right. I should have mentioned that in my case I don't want to modify the class' interface, but rather the content of its methods.
Your answer was really helpful. Thank you :)
Are you asking about (1) true class replacement at run-time, or (2) facilities to transform the class when it's loaded or (3) languages which support dynamic class loading ?
Java support dynamic class loading with ClassLoader, transformation with ClassFileTransformer, but no true class replacement.
I'm not sure for C#, but I think you can emit code at run-time and create new class dynamically, so you can achieve (3) and probably (2).
True class replacement is mostly supported only by dynamic language, e.g. Smalltalk, Ruby, I guess Python and a few others. This requires the transformation of the instances of the class to match the new shape. They usually initialize the new fields to nil if the class changes.
AFAIK, dynamic languages ported to the JVM make extensive hacking of ClassLoader to support class replacement at run-time. For JRuby, see A first taste of invoke dynamic to get more pointers how they do it now, what's problematic and how the upcoming invokedynamic might help.
This is not offered in statically typed languages because of the complication with the type system. If a method signature change in a class, other existing classes already loaded might not necessary comply with the new method signature which is not safe. In java you can however change a method as long as the signature is the same using the Java Platform Debugger Architecture.
There have been some attempt to add this feature to Java, and/or statically typed languages:
Runtime support for type-safe dynamic Java classes
Supporting Unanticipated Dynamic Adaptation of Application Behaviour
A Technique for Dynamic Updating of Java Software
This paper provide a general overview of related problems
Influence of type systems on dynamic software evolution
Not sure exactly if that address you initial question, but these pointers might be interesting for your thesis anyway.
The Java language doesn't support class file replacement. The JVM exposes the feature via the classes you mention. Therefore all languages which have been ported to the JVM can take advantage of it.
Erlang supports hot code swapping, and if you are looking also for theoretical frameworks that model dynamic class updates, you can take a look at the Creol language (interpreted).
Objective-C's runtime library supports dynamic construction and registration of classes, lazy method registration and "method swizzling" by which method implementations can be switched at runtime. Previous versions supported "Class swizzling" by which a class could be substituted for another at runtime, but now method swizzling is used instead. Here's the reference doc.