Choose and test java decompiler [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
Now I'm trying to find the best java decompiler, I found these:
http://java.decompiler.free.fr/
http://www.reversed-java.com/fernflower/
http://dj.navexpress.com/
http://cavaj-java-decompiler.en.softonic.com/
With these decompilers I handle byte code of this class:
public class ss
{
public static void main(String args[])
{
try{
System.out.println("try");
}
catch(Exception e)
{
System.out.println("catch");
}
finally
{System.out.println("finally");}
}
}
and I got the following results:
fernflower:
public class ss {
public static void main(String[] var0) {
try {
System.out.println("try");
} catch (Exception var5) {
System.out.println("catch");
} finally {
System.out.println("finally");
}
}
}
DJ Java Decompiler:
import java.io.PrintStream;
public class ss
{
public ss()
{
}
public static void main(String args[])
{
System.out.println("try");
System.out.println("finally");
break MISSING_BLOCK_LABEL_50;
Exception exception;
exception;
System.out.println("catch");
System.out.println("finally");
break MISSING_BLOCK_LABEL_50;
Exception exception1;
exception1;
System.out.println("finally");
throw exception1;
}
}
cavaj:
import java.io.PrintStream;
public class ss
{
public ss()
{
}
public static void main(String args[])
{
System.out.println("try");
System.out.println("finally");
break MISSING_BLOCK_LABEL_50;
Exception exception;
exception;
System.out.println("catch");
System.out.println("finally");
break MISSING_BLOCK_LABEL_50;
Exception exception1;
exception1;
System.out.println("finally");
throw exception1;
}
}
http://java.decompiler.free.fr/:
import java.io.PrintStream;
public class ss
{
public static void main(String[] paramArrayOfString)
{
try
{
System.out.println("try");
}
catch (Exception localException)
{
System.out.println("catch");
}
finally {
System.out.println("finally");
}
}
}
I see that the best result in decompiler: http://java.decompiler.free.fr/
To test, I wrote very simple code. What do you think, what code to write to test decompilers? Maybe the idea is to better than a try{} catch(){} finally{}?

The code that you use to test should test the features available the in JDK used to compile the target class. For example, if you know that your target is written in Java 1.5, it is reasonable to assume that the code might include generics, so you will want to make sure that your chosen decompiler handles them properly. In my experience, the freely available decompilers tend to lag behind the JDK releases in terms of the features they support by 1-2 releases.
Based on personal trial and error, JD tends to do the best job in general. However, if you're decompiling code that was written in 1.3 or lower, I'd also suggest you give JODE a try.
EDIT, 5 years later:
CFR, Procyon, and Fernflower lead the way in this space.

Procyon has it's own comparison.

I have been using http://java.decompiler.free.fr/ for a long time now and found it to be the best one. In particular I used it to decompile a third-party jar and I was able to modify the source code as well with it.
Its easy to use and the UI is also neat and clean.
Update: Java Decompiler is no longer available on http://java.decompiler.free.fr/. It has new link http://jd.benow.ca/ from where it can be downloaded.

If you anticipate to get any meaningful results, you really should test with a bit more non-trivial code. Fernflower was created with the aim of handling highly unusual and obfuscated bytecode. Thus decompiling such simple snippets is no big deal. By the way, if you are interested in testing the stand-alone version of Fernflower drop me a note at fernflower(dot)decompiler(at)gmail(dot)com. Version 0.8.4 is now in semi-public beta (however not available on the website yet).

It looks like fernflower and JD Java Decompiler are producing decompiled code that is as good as is possible for this particular testcase. The other two aren't doing a good job, IMO.
What do you think, what code to write to test decompilers?
Write more complicated code using all available constructs.
Try them out on some real code.
Try them out on some real code that has been obfuscated.
When trying out code that you compile from source, experiment with different "-g" options, and with different Java compilers.

http://www.reversed-java.com/fernflower/, see my comparison on github.com /vorburger/ScratchApplet

For information, JD supports switch(enum), switch(string), assert statements and for-each loops.
About the -g(javac) options,
if you omit the line numbers, JD can
not reconstruct the original flow of
instructions : the types of loop can
not be determinate, the multiple
assigments can not be regenerate, and
the algorithm used to realign source
code can not work.
if you omit the
local variable data, JD can not,
sometime, determine the exact range
of variables. It's problematic.

Ok, this is written from my mobile phone so bear with me.
1st of all, every java file codes are compiled in bytecode in their respective .class file. This means that constants are stored AS IS (hence strings can easily be retrieved) and variables are assigned to a register that is then put on a stack program execution when the JVM process the class file.
The reason your exception block are not returned to the original code you've written is because of the way javac compiled & translated the code to java bytecode.
If you want to know which decompiler works best, write all java well known statements (for loop, if statement, while loop) with some expressions & see what best represent your original code.
Good luck.

It's been a while since any feedback to this thread. However since I found it and took the input seriously I feel it important to give an update.
I have used Java Decompiler Free with good success. However, recently I accidentally deleted quite a bit of code of a production J2EE application. assumed JD Free would handle it, but it doesn't handle generics at all. Plus there was code where it handled variable initialization totally wrong. What I ended up with was a total mess.
There may not be anything out there that will to the job correctly. In my case it's just another lesson in backup, backup, backup. I need a de-compiler that handles generics properly in order to do a mass recovery. But some accuracy of handling variables would also help. It is too much to ask a tool to spit out the original code. But what I have seen so far will compile but will not function properly, generics aside. So I suppose it's going to be a long week before Christmas!!

Related

when we use return statement inside if block why compiler not giving any error? [duplicate]

This question already has answers here:
Why does Java have an "unreachable statement" compiler error?
(8 answers)
Closed 6 years ago.
The following code gives an unreachable statement compiler error
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
Sometimes for testing purposes a want to prevent a method from being called, so a quick way to do it (instead of commenting it out everywhere it's used) is to return immediately from the method so that the method does nothing. What I then always do to get arround the compiler error is this
public static void main(String[] args) {
if (true) {
return;
}
System.out.println("unreachable");
}
I'm just curious, why is it a compiler error?? Will it break the Java bytecode somehow, is it to protect the programmer or is it something else?
Also (and this to me is more interesting), if compiling java to bytecode does any kind of optimization (or even if it doesn't) then why won't it detect the blatant unreachable code in the second example? What would the compiler pseudo code be for checking if a statement is unreachable?
Unreachable code is meaningless, so the compile-time error is helpful. The reason why it won’t be detected at the second example is, like you expect, for testing / debugging purposes. It’s explained in The Specification:
if (false) { x=3; }
does not result in a compile-time error. An optimizing compiler may
realize that the statement x=3; will never be executed and may choose
to omit the code for that statement from the generated class file, but
the statement x=3; is not regarded as "unreachable" in the technical
sense specified here.
The rationale for this differing treatment is to allow programmers to
define "flag variables" such as:
static final boolean DEBUG = false;
and then write code such as:
if (DEBUG) { x=3; }
The idea is that it should be possible to change the value of DEBUG
from false to true or from true to false and then compile the code
correctly with no other changes to the program text.
Reference: http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
Its because the compiler writer assumed that the human at the controls is dumb, and probably didn't mean to add code that would never be executed - so by throwing an error, it attempts to prevent you from inadvertently creating a code path that cannot be executed - instead forcing you to make a decision about it (even though, as you have proven, you still can work around it).
This error is mainly there to prevent programmer errors (a swap of 2 lines or more). In the second snippet, you make it clear that you don't care about the system.out.println().
Will it break the Java bytecode somehow, is it to protect the programmer or is it something else?
This is not required as far as Java/JVM is concerned. The sole purpose of this compilation error is to avoid silly programmer mistakes. Consider the following JavaScript code:
function f() {
return
{
answer: 42
}
}
This function returns undefined as the JavaScript engine adds semicolon at the end of the line and ignores dead-code (as it thinks). Java compiler is more clever and when it discoveres you are doing something clearly and obviously wrong, it won't let you do this. There is no way on earth you intended to have dead-code. This somehow fits into the Java premise of being a safe language.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
says:
14.21. Unreachable Statements
It is a compile-time error if a statement cannot be executed because it is unreachable.
Example 1:
In this case you are return before any statement because of it compiler never going to execute that code.
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
In second code I have put the statement above of return and its work now :)
Example 2:
public static void main(String[] args) {
System.out.println("unreachable"); // Put the statement before return
return;
}
The reason behind this is that if you return sometime then code after it never going to execute because you already return the function data and as so it is shown unreachable code.
It's because it's a waste of resources for it to even be there. Also, the compiler designers don't want to assume what they can strip out, but would rather force you to remove either the code that makes it unreachable or the unreachable code itself. They don't know what is supposed to be there. There's a difference between the optimizations where they tweak your code to be a bit more efficient when it's compiled down to machine code and blatantly just removing code "you didn't need."

Why doesn't Kotlin require try and catch explicitly

For example:
FileOutputStream("file")
would compile in Kotlin, but in Java it would give a compiler error. Why?
Kotlin does away with Java's checked exceptions. Exceptions checked at compile time and declared in method signatures, though familiar to Java developers, are widely considered a failed experiment outside and to some degree inside the Java community.
So Kotlin did away with them, and with some of the boilerplate associated with using resources (like FileOutputStream) with the .use method shorthand for Java 7's try-with-resources.
It can be difficult to answer without letting some opinions interfere. I will just say that Kotlin is aimed at large software projects and give you what the Kotlin team claims regarding checked exceptions (from https://kotlinlang.org/docs/reference/exceptions.html):
Checked Exceptions
Kotlin does not have checked exceptions. There are many reasons for
this, but we will provide a simple example.
The following is an example interface of the JDK implemented by
StringBuilder class:
Appendable append(CharSequence csq) throws IOException; What does this
signature say? It says that every time I append a string to something
(a StringBuilder, some kind of a log, a console, etc.) I have to catch
those IOExceptions. Why? Because it might be performing IO (Writer
also implements Appendable)… So it results into this kind of code all
over the place:
try {
log.append(message)
}
catch (IOException e) {
// Must be safe
}
And this is no good, see Effective Java, Item 65: Don't ignore
exceptions.
Bruce Eckel says in Does Java need Checked Exceptions?:
Examination of small programs leads to the conclusion that requiring
exception specifications could both enhance developer productivity and
enhance code quality, but experience with large software projects
suggests a different result – decreased productivity and little or no
increase in code quality.
Other citations of this sort:
Java's checked exceptions were a mistake (Rod Waldhoff)
The Trouble with Checked Exceptions (Anders Hejlsberg)

throw user defined exception in single statement in java

Recently i attended an interview. one of the questions asked in technical interview round is "how can you throw a user defined exception using single statement".
i wrote the code as
class MyException extends Exception{
public MyExeption(String err){
super(err);
}
class sample{
public static void main(String a[]){
throw new MyException("Error");
}
but he said that i used 2 statements 1 for throw statement and other for super() statement.
what is the answer. plese clear my doubt. thank you
I am sure that the interviewer was looking for you to extend Exception anonymously:
throw new Exception("Error") {
// Here is what makes the exception user-defined.
// You do not need to override anything, but if you want, you can:
public String getMessage() {
return "Here is your user-defined exception!";
}
};
Literally, the question asks to throw. Not to declare & throw.
throw new MyUserDefinedException("It was declared elsewhere.");
If you want to declare & throw, that's what the other answer said. Of course this is complete crap code with no purpose. I would penalize or fire somebody, who used this kind of approach in real work.
throw new IllegalArgumentException("BS interview question, take another job."){};
It also doesn't work, over RMI :( The worst thing is, how many days of debugging ($1000s..) it will take to uncover it again, if some twit ever writes this bug for you.
They may be testing your Java understanding, but it seems likely these clowns don't actually know how to use/ what to do with Java themselves.
My interview questions ask actual real business questions. They can be highly challenging.
I don't look for idiots who can do stupid pointless things within the language idiom, I look for people who can solve not-easy problems within a typical business application.

What is the exception I should be catching on the dotted line?

I have a problem at school. I'm new to programing and I need some help. Please complete the dotted line:
import java.net.*;
import java.io.*
public class Test{
public static void main (String arg[]}
int x=0;
try {
ServerSocket s=new ServerSocket ( k );
s.close();
}
catch (..........................) {x++;}
catch(IOException e) {}
}
System.out.println( "Total "+ x); }
}
Look up in the documentation what exceptions the constructor of ServerSocket can throw and what exception the close function of ServerSocket can throw. One of them is probably IOException, just look up what else.
A hint: if you use a modern IDE, it'll tell you. For example, just write without the try and catch blocks
import java.net.*; import java.io.*
public class Test{
public static void main (String arg[]}
int x=0;
ServerSocket s=new ServerSocket ( k );
s.close();
System.out.println( "Total "+ x); }
}
The IDE will underline the code and give you a suggestion, click on it and it'll insert the appropriate Exceptions automatically.
The answer can be found at the JavaDoc for ServerSocket constructor that you use.
You need to catch (or declare that your method throws) every Checked Exception that is declared by the code that you are calling. These are documented in the JavaDoc and on the method signature. Unchecked exceptions, like IllegalArguementException, do not need to be caught.
To make the code compile, the line should read:
catch (StackOverflowError exc) {x++;}
If you use an IDE, such as Eclipse, you can easily fix those problems and many others, as the IDE will point out exactly what Exceptions need to be caught, saving you from a trip to the Javadoc page which, by the way, is easily accessed directly from the IDE.
#akf: That's not the opinion of the instructors of some major CS schools. For example, the "Introduction to Computer Science | Programming Methodology" course of Stanford uses a modified version of Eclipse. I think it's a much better way to learn a language, avoiding those situations where you are fixing a problem, compile, and then fix the new problem. This can be frustrating to newcomers. An IDE is just a tool to aid programming, it doesn't cause dependence, and it certainly won't stop you from coding without it.
I do agree, however, that it's important to know the basics, as far as using java or javac is concerned, just in case you ever find yourself with a terminal in front of you.
As you mention in your comment on Henri, you have to choose between either SecurityException or IllegalArgumentException.
The significance here lies in the variable x. What is x supposed to count? My guess would be the former, but there should be a hint in your assignment.
(BTW: I only see a mention of SecurityException besides IOException in the documentation)

How expensive are Exceptions [duplicate]

This question already has answers here:
What are the effects of exceptions on performance in Java?
(18 answers)
Closed 9 years ago.
Do you know how expensive exception throwing and handling in java is?
We had several discussions about the real cost of exceptions in our team. Some avoid them as often as possible, some say the loss of performance by using exceptions is overrated.
Today I found the following piece of code in our software:
private void doSomething()
{
try
{
doSomethingElse();
}
catch(DidNotWorkException e)
{
log("A Message");
}
goOn();
}
private void doSomethingElse()
{
if(isSoAndSo())
{
throw new DidNotWorkException();
}
goOnAgain();
}
How is the performance of this compared to
private void doSomething()
{
doSomethingElse();
goOn();
}
private void doSomethingElse()
{
if(isSoAndSo())
{
log("A Message");
return;
}
goOnAgain();
}
I don't want to discuss code aesthetic or anything, it's just about runtime behaviour!
Do you have real experiences/measurements?
Exceptions are not free... so they are expensive :-)
The book Effective Java covers this in good detail.
Item 39 Use exceptions only for exceptional conditions.
Item 40 Use exceptions for recoverable conditions
The author found that exceptions resulted in the code tunning 70 times slower for his test case on his machine with his particular VM and OS combo.
The slowest part of throwing an exception is filling in the stack trace.
If you pre-create your exception and re-use it, the JIT may optimize it down to "a machine level goto."
All that having been said, unless the code from your question is in a really tight loop, the difference will be negligible.
The slow part about exceptions is building the stack trace (in the constructor of java.lang.Throwable), which depends on stack depth. Throwing in itself is not slow.
Use exceptions to signal failures. The performance impact then is negligible and the stack trace helps to pin-point the failure's cause.
If you need exceptions for control flow (not recommended), and profiling shows that exceptions are the bottleneck, then create an Exception subclass that overrides fillInStackTrace() with an empty implementation. Alternatively (or additionally) instantiate only one exception, store it in a field and always throw the same instance.
The following demonstrates exceptions without stack traces by adding one simple method to the micro benchmark (albeit flawed) in the accepted answer:
public class DidNotWorkException extends Exception {
public Throwable fillInStackTrace() {
return this;
}
}
Running it using the JVM in -server mode (version 1.6.0_24 on Windows 7) results in:
Exception:99ms
Boolean:12ms
Exception:92ms
Boolean:11ms
The difference is small enough to be ignorable in practice.
I haven't bothered to read up on Exceptions but doing a very quick test with some modified code of yours I come to the conclusion that the Exception circumstance quite a lot slower than the boolean case.
I got the following results:
Exception:20891ms
Boolean:62ms
From this code:
public class Test {
public static void main(String args[]) {
Test t = new Test();
t.testException();
t.testBoolean();
}
public void testException() {
long start = System.currentTimeMillis();
for(long i = 0; i <= 10000000L; ++i)
doSomethingException();
System.out.println("Exception:" + (System.currentTimeMillis()-start) + "ms");
}
public void testBoolean() {
long start = System.currentTimeMillis();
for(long i = 0; i <= 10000000L; ++i)
doSomething();
System.out.println("Boolean:" + (System.currentTimeMillis()-start) + "ms");
}
private void doSomethingException() {
try {
doSomethingElseException();
} catch(DidNotWorkException e) {
//Msg
}
}
private void doSomethingElseException() throws DidNotWorkException {
if(!isSoAndSo()) {
throw new DidNotWorkException();
}
}
private void doSomething() {
if(!doSomethingElse())
;//Msg
}
private boolean doSomethingElse() {
if(!isSoAndSo())
return false;
return true;
}
private boolean isSoAndSo() { return false; }
public class DidNotWorkException extends Exception {}
}
I foolishly didn't read my code well enough and previously had a bug in it (how embarassing), if someone could triple check this code I'd very much appriciate it, just in case I'm going senile.
My specification is:
Compiled and run on 1.5.0_16
Sun JVM
WinXP SP3
Intel Centrino Duo T7200 (2.00Ghz, 977Mhz)
2.00 GB Ram
In my opinion you should notice that the non-exception methods don't give the log error in doSomethingElse but instead return a boolean so that the calling code can deal with a failure. If there are multiple areas in which this can fail then logging an error inside or throwing an Exception might be needed.
This is inherently JVM specific, so you should not blindly trust whatever advice is given, but actually measure in your situation. It shouldn't be hard to create a "throw a million Exceptions and print out the difference of System.currentTimeMillis" to get a rough idea.
For the code snippet you list, I would personally require the original author to thoroughly document why he used exception throwing here as it is not the "path of least surprises" which is crucial to maintaining it later.
(Whenever you do something in a convoluted way you cause unneccesary work to be done by the reader in order to understand why you did it like that instead of just the usual way - that work must be justified in my opinion by the author carefully explaining why it was done like that as there MUST be a reason).
Exceptions are a very, very useful tool, but should only be used when necessary :)
I have no real measurements, but throwing an exception is more expensive.
Ok, this is a link regarding the .NET framework, but I think the same applies to Java as well:
exceptions & performance
That said, you should not hesitate to use them when appropriate. That is : do not use them for flow-control, but use them when something exceptional happend; something that you didn't expect to happen.
I think if we stick to using exceptions where they are needed (exceptional conditions), the benefits far outweigh any performance penalty you might be paying. I say might since the cost is really a function of the frequency with which exceptions are thrown in the running application.
In the example you give, it looks like the failure is not unexpected or catastrophic, so the method should really be returning a bool to signal its success status rather than using exceptions, thus making them part of regular control flow.
In the few performace improvement works that I have been involved in, cost of exceptions has been fairly low. You would be spending far more time time in improving the complexity of common, hightly repeating operations.
Thank you for all the responses.
I finally followed Thorbjørn's suggestion and wrote a little test programm, measuring the performance myself. The result is: No difference between the two variants (in matters of performance).
Even though I didn't ask about code aesthetics or something, i.e. what the intention of exceptions was etc. most of you addressed also that topic. But in reality things are not always that clear... In the case under consideration the code was born a long time ago when the situation in which the exception is thrown seemed to be an exceptional one. Today the library is used differently, behaviour and usage of the different applications changed, test coverage is not very well, but the code still does it's job, just a little bit too slow (That's why I asked for performance!!). In that situation, I think, there should be a good reason for changing from A to B, which, in my opinion, can't be "That's not what exceptions were made for!".
It turned out that the logging ("A message") is (compared to everything else happening) very expensive, so I think, I'll get rid of this.
EDIT:
The test code is exactly like the one in the original post, called by a method testPerfomance() in a loop which is surrounded by System.currentTimeMillis()-calls to get the execution time...but:
I reviewed the test code now, turned of everything else (the log statement) and looping a 100 times more, than before and it turns out that you save 4.7 sec for a million calls when using B instead of A from the original post. As Ron said fillStackTrace is the most expensive part (+1 for that) and you can save nearly the same (4.5 sec) if you overwrite it (in the case you don't need it, like me). All in all it's still a nearly-zero-difference in my case, since the code is called 1000 times an hour and the measurements show I can save 4.5 millis in that time...
So, my 1st answer part above was a little misleading, but what I said about balancing the cost-benefit of a refactoring remains true.
I think you're asking this from slightly the wrong angle. Exceptions are designed to be used to signal exceptional cases, and as a program flow mechanism for those cases. So the question you should be asking is, does the "logic" of the code call for exceptions.
Exceptions are generally designed to perform well enough in the use for which they are intended. If they're used in such a way that they're a bottleneck, then above all, that's probably an indication that they're just being used for "the wrong thing" full stop-- i.e. what you have underlyingly is a program design problem rather than a performance problem.
Conversely, if the exception appears to be being "used for the right thing", then that probably means it'll also perform OK.
Let's say exception won't occur when trying to execute statements 1 and 2. Are there ANY performance hits between those two sample-codes?
If no, what if the DoSomething() method has to do a huuuge amount of work (loads of calls to other methods, etc.)?
1:
try
{
DoSomething();
}
catch (...)
{
...
}
2:
DoSomething();

Categories

Resources