This question already has answers here:
Java conditional compilation: how to prevent code chunks from being compiled?
(9 answers)
Closed 9 years ago.
I'm wondering if there if a Java equivalent for C's
#if 0
... Some Code ...
#endif
Which can be used around code blocks we don't want to compile. Adding block quotes:
/*
... Some Code ...
*/
also has the same effect, but the problem is, we have to ensure there are no single line comments
// some comment
in the block.
static final fields can be use for conditional compilation.
static final boolean DEBUG = false;
if (DEBUG) {
some code ....
}
some code will be removed by the compiler.
It is also possible to use the assert keyword to enable and disable some part of the code. Use java -ea: .. to control if the code should be enabled or disable. See http://docs.oracle.com/javase/1.5.0/docs/guide/language/assert.html
There are no pre-processor directives in Java. Your best choice is commenting out code.
There are several solutions:
Use a preprocessor - I think that it will work with the standard CPP. There were some Java specific proprocessors as jappo and java+ that you can try
Replace the #if 0 with a true if:
if(false) {
code
}
The condition can be refined by querying the system properties:
if(System.getProperty("NO_COMPILE").equals("true")) {
code
}
This has the advantage that it can be easily set either from ANT or from Eclipse.
EDIT: Please remark that with if the code will actually be compiled and present in the .class files. Moreover, although querying system properties is more elegant, is done at runtime not at compile time hence is not quite inline with original requirement. The if(false) is on a 2nd tought better.
EDIT2: an even better solution I have just found: http://prebop.sourceforge.net/
I can't even begin to imagine why this is an issue (as described) but I suspect the easiest thing to do is to grep for // in the code before you compile it (or commit it to your versioning repo). I don't think there's anything in eclipse (if that's what you're using) to help you and I'm almost positive that java has no built in mechanism like the one you're describing in C.
I saw this somewhere a while ago:
// /*
class SomeClass{
int withSomeField;
..............
}
// */
And you can put the //s in and and remove them as necessary. It's probably multiline comments that would cause problem if they were in there, though.
if(false) works well for me (using Eclipse).
you can just use Java Preprocessor and I guess it will be better way than flags
http://code.google.com/p/java-comment-preprocessor/
flags of course allow to cut and to add blocks on the compilation phase but preprocessor allows to make the process much more flexible
Instead of trying to make the code conditional by preprocessing the source-code (as C does), use object oriented programming: use design patterns such as Strategy, and dependency injection, to make code conditional.
There's not a Java-equivalent of the preprocessor's directive used in C/C++ languages.
Anyhow, you could do something similar using annotations or ANT, as briefly explained here
Using annotations to add C like preprocessor directives
or here
How to do Conditional Compilation with Java
Related
I know Java does not have pre-processor, but I struggle to find a way to do this.
I am looking to create macros to improve code readibility, to specify which of the functions or parameters are for input or output specifically. In C, this would be done like this :
#define IN
#define OUT
And these would just be used before the variables and functions. Can I simulate the same behavior in Java?
I did not manage to find a way to do this. The only way I found was including defines in the code and first using the cpp pre-processor to replace them, and then run the java code, but maybe there is a better way of doing this?
Java indeed does not have a pre-processor, and your use case doesn't require that either: you aren't actually preprocessing the code, you just put in some tags that the compiler can ignore.
What you are looking for are "annotations" - you basically want to annotate your code with some nice text that will not affect the compiler.
This basically requires defining some specialized Java types for this using the #interface keyword and then you can use them to write things like:
public void doStuff(#Input invar, #Output outvar) {
...
These annotations can be simply:
#interface Input {}
#interface Output {}
or you can add more features and even use reflection to examine them in runtime.
See the linked documentation above for more details.
Is it possible to do method swizzling in android using java? i would like to intercept a system method and log its parameters then process it normally
I think that technique could not be used using Java in any environment.
Maybe you could achieve a similar result using AOP.
But what you can do with that looks limited on Android. See Aspect-oriented programming in android. In fact, since you won't be compiling the target code (system method), compile-time weaving (which appears to be all you could use on Android) will be useless for this case. As is this answer I suppose.
One other thought... I guess you want to do this logging consistently. But if you needed this to debug a problem, you could do it using a conditional breakpoint in Eclipse.
A conditional expression can contain arbitrary Java code and may
contain more than one statement, allowing breakpoint conditions to
implement features like tracing. For example, a condition can execute
a print statement and then return a hard coded value to never suspend
("System.out.println(...); return false;").
I don't know specifically whether this works with methods in the Android SDK. But it does work with methods in the Java SDK. For example, here is simple code:
System.err.println("foo");
I made a conditional breakpoint in PrintStream.print, like this:
System.err.println("hello: " + arg0);
return false;
And the console output when debugging in the program is this:
hello: foo
foo
Note that since the JDK is not compiled with debug symbols, I can't refer to method parameters by name, but using the arg0..argn.
I have an app that gets the content of an html file.
Lets say the text of the page is:
String[] arr = new String[] {"!","#","#"};
for (String str : arr) {
write(str);
}
Can I somehow compile this text and run the code within my app?
Thanks
Use Janino. It's a java runtime in-memory compiler. Way easier than BCEL and the likes.
From the homepage:
"What is Janino?
Janino is a super-small, super-fast Java™ compiler. Not only can it compile a set of source files to a set of class files like the JAVAC tool, but also can it compile a Java™ expression, block, class body or source file in memory, load the bytecode and execute it directly in the same JVM. Janino is not intended to be a development tool, but an embedded compiler for run-time compilation purposes...
You can use the javac compiler, or the Java Compiler API or the BeanShell library (or similar). You can compile it any number of ways, none terribly simple which often leads to finding another way to solve your problem.
Instead of generating source and compiling its common to generate byte code directly using ASM, Javaassist, BCEL or the like
This appears to be the same as
for(char ch: "!##".toCharArray())
write(ch);
which is likely to be the same as
write("!##");
Since the question is tagged android:
The answers posted so far only apply to the “standard” JVM, not to Android's Dalvik VM. In principle, it is possible on Android too. I don't know if there's an existing Java compiler that you can embed, but you would probably generate the final Dalvik bytecode using dexmaker. It may be possible to combine an existing Java compiler with dexmaker.
But please think twice before attempting anything like this, and be very careful. The last thing you want is a way for an attacker to execute arbitrary code on your user's hardware.
You can try javassist, it's not full Java though.
This is not usually that hard to do, but I have to ask can you give more detail on exactly what it is you are trying to accomplish. I do this type thing all the time. This is just another example of getting information from the user and using it somewhere else in your code. Since your using java maybe look at the string API http://docs.oracle.com/javase/6/docs/api/java/lang/String.html and the string tokenizer http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/package-summary.html
Now you can break the string down into single values one word or other value at a time. From there you can use functions such as isNAN() from the float or double class to determine if it a number or string or whatever it is your testing for. Now you know what you’re dealing with you can reconstructed the data in a usable form.
Note for values if you want to use them as values use Float(string value) constructor. i.e Float x = new Float(myString)
Goal
Detecting where comparisons between and copies of variables are made
Inject code near the line where the operation has happened
The purpose of the code: everytime the class is ran make a counter increase
General purpose: count the amount of comparisons and copies made after execution with certain parameters
2 options
Note: I always have a .java file to begin with
1) Edit java file
Find comparisons with regex and inject pieces of code near the line
And then compile the class (My application uses JavaCompiler)
2)Use ASM Bytecode engineering
Also detecting where the events i want to track and inject pieces into the bytecode
And then use the (already compiled but modified) class
My Question
What is the best/cleanest way? Is there a better way to do this?
If you go for the Java route, you don't want to use regexes -- you want a real java parser. So that may influence your decision. Mind, the Oracle JVM includes one, as part of their internal private classes that implement the java compiler, so you don't actually have to write one yourself if you don't want to. But decoding the Oracle AST is not a 5 minute task either. And, of course, using that is not portable if that's important.
If you go the ASM route, the bytecode will initially be easier to analyze, since the semantics are a lot simpler. Whether the simplicity of analyses outweighs the unfamiliarity is unknown in terms of net time to your solution. In the end, in terms of generated code, neither is "better".
There is an apparent simplicity of just looking at generated java source code and "knowing" that What You See Is What You Get vs doing primitive dumps of class files for debugging and etc., but all that apparently simplicity is there because of your already existing comfortability with the Java lanaguage. Once you spend some time dredging through byte code that, too, will become comfortable. Just a question whether it's worth the time to you to get there in the first place.
Generally it all depends how comfortable you are with either option and how critical is performance aspect. The bytecode manipulation will be much faster and somewhat simpler, but you'll have to understand how bytecode works and how to use ASM framework.
Intercepting variable access is probably one of the simplest use cases for ASM. You could find a few more complex scenarios in this AOSD'07 paper.
Here is simplified code for intercepting variable access:
ClassReader cr = ...;
ClassWriter cw = ...;
cr.accept(new MethodVisitor(cw) {
public void visitVarInsn(int opcode, int var) {
if(opcode == ALOAD) { // loading Object var
... insert method call
}
}
});
If it was me i'd probably use the ASM option.
If you need a tutorial on ASM I stumbled upon this user-written tutorial click here
I want to replace calls to a given class with calls to anther class within a method body whilst parsing compiled class files...
or put another way, is there a method of detecting usages of a given class in a method and replacing just that part of the method using something like javaassist.
for example.. if I had the compiled version of
class A { public int m() { int i = 2; B.multiply(i,i); return i; } }
is there a method of detecting the use of B and then altering the code to perform
class A { public int m() { int i = 2; C.divide(i,i); return i; } }
I know the alternative would be to write a parser to grep the source files for usages but I would prefer a more elegant solution such as using reflection to generate new compiled class files.
Any thoughts ?
As #djna says, it is possible to modify bytecode files before you load them, but you probably do not want to do this:
The code that does the code modification is likely to be complex and hard to maintain.
The code that has been modified is likely to be difficult to debug. For a start, a source level debugger will show you source code that no longer corresponds to the code that you are actually editing.
Bytecode rewriting is useful in certain cases. For example, JDO implementations use bytecode rewriting to replace object member fetches with calls into the persistence libraries. However, if you have access to the source code for these files, you'll get a better (i.e. more maintainable) solution by preprocessing (or generating) the source code.
EDIT: and AOP or Groovy sound like viable alternatives too, depending on the extent of rewriting that you anticipate doing.
BCEL or ASM.
I recently looked at a number of libraries for reading Java class files. BCEL was the fastest, had the least number of dependencies, compiled out of the box, and had a deliciously simple API. I preferred BCEL to ASM because ASM has more dependencies (although the API is reputedly simpler).
AspectJ, as previously mentioned, is another viable option.
BCEL is truly simple. You can get a list of methods in three lines of code:
ClassParser cp = new ClassParser( "A.class" );
JavaClass jc = cp.parse();
Method[] m = jc.getMethods();
There are other API facilities for further introspection, including, I believe, ways to get the instructions in a method. However, this solution will likely be more laborious than AspectJ.
Another possibility is to change the multiply or divide methods themselves, rather than trying to change all instances of the code that calls the operation. That would be an easier road to take with BCEL (or ASM).
The format of byte code for compiled Java is specified and products exist that manipulate it.
This library appears to have the capability you need. I've no idea how easy it is to do these transformations reliably.
If you don't mind using Groovy, you can intercept the call to B.multiply and replace it with C.divide. You can find an example here.
It's much easier to perform these operations ahead-of-time, where the executable on disk is modified before launching the application. Manipulating the code in memory at run time is even more prone to errors than manipulating code in memory in C/C++. Why do you need to do this?