Why is this loop changed?
up vote
12
down vote
favorite
I just encountered this decompiled class file of my class.
MyClass
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
the while loop has been changed to for loop in the class file.
Decompiled MyClass
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
Why is this loop changed to for?
I think it might be another way of code optimization by compiler, could be wrong.
I just wanted to know if it is, what advantages does for loop provides over while loop or other loop?
What is category of such code optimizations?
java loops optimization
|
show 5 more comments
up vote
12
down vote
favorite
I just encountered this decompiled class file of my class.
MyClass
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
the while loop has been changed to for loop in the class file.
Decompiled MyClass
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
Why is this loop changed to for?
I think it might be another way of code optimization by compiler, could be wrong.
I just wanted to know if it is, what advantages does for loop provides over while loop or other loop?
What is category of such code optimizations?
java loops optimization
6
Hard to tell from source code along, but it might just be a choice of the decompiler to show you this version. Note that a decompiler has to "guess" a bit - it chooses one possible source code that might lead to the given bytecode.
– Hulk
2 hours ago
2
@KumarAnkit - No necessarily optimization, no. There isn't a one-to-one relationship between source constructs and bytecode. That's what Hulk means when he/she says "a decompiler has to 'guess' a bit."
– T.J. Crowder
1 hour ago
4
@KumarAnkit what people are trying to explain is that maybe there's no optimization at all. Try translating a hindi (or whatever is your regional dialect) sentence in english using Google translate, and then back to hindi. You'll be lucky if it's the same sentence than at the beginning. Here it's the same thing, got it?
– Dici
1 hour ago
5
@KumarAnkit -for
(andwhile
, etc.) don't exist at the bytecode level. It's jump instructions, assignments, etc. One decompiler might look at some bytecode and say "that looks like afor
" while another might look at it and say "that looks like awhile
". "So, does it mean these loops are identical at the byte-code level?" Not necessarily. If you compile the code output by a decompiler, you don't necessarily end up with identical bytecode. In fact, I suspect you rarely would.
– T.J. Crowder
1 hour ago
1
@dici, thanks, I can understand this language as well. I got that it does not mean optimization, was just little bit surprised to have found it
– KumarAnkit
1 hour ago
|
show 5 more comments
up vote
12
down vote
favorite
up vote
12
down vote
favorite
I just encountered this decompiled class file of my class.
MyClass
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
the while loop has been changed to for loop in the class file.
Decompiled MyClass
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
Why is this loop changed to for?
I think it might be another way of code optimization by compiler, could be wrong.
I just wanted to know if it is, what advantages does for loop provides over while loop or other loop?
What is category of such code optimizations?
java loops optimization
I just encountered this decompiled class file of my class.
MyClass
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
the while loop has been changed to for loop in the class file.
Decompiled MyClass
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
Why is this loop changed to for?
I think it might be another way of code optimization by compiler, could be wrong.
I just wanted to know if it is, what advantages does for loop provides over while loop or other loop?
What is category of such code optimizations?
java loops optimization
java loops optimization
edited 44 mins ago
Nikhil Kinkar
568421
568421
asked 2 hours ago
KumarAnkit
669
669
6
Hard to tell from source code along, but it might just be a choice of the decompiler to show you this version. Note that a decompiler has to "guess" a bit - it chooses one possible source code that might lead to the given bytecode.
– Hulk
2 hours ago
2
@KumarAnkit - No necessarily optimization, no. There isn't a one-to-one relationship between source constructs and bytecode. That's what Hulk means when he/she says "a decompiler has to 'guess' a bit."
– T.J. Crowder
1 hour ago
4
@KumarAnkit what people are trying to explain is that maybe there's no optimization at all. Try translating a hindi (or whatever is your regional dialect) sentence in english using Google translate, and then back to hindi. You'll be lucky if it's the same sentence than at the beginning. Here it's the same thing, got it?
– Dici
1 hour ago
5
@KumarAnkit -for
(andwhile
, etc.) don't exist at the bytecode level. It's jump instructions, assignments, etc. One decompiler might look at some bytecode and say "that looks like afor
" while another might look at it and say "that looks like awhile
". "So, does it mean these loops are identical at the byte-code level?" Not necessarily. If you compile the code output by a decompiler, you don't necessarily end up with identical bytecode. In fact, I suspect you rarely would.
– T.J. Crowder
1 hour ago
1
@dici, thanks, I can understand this language as well. I got that it does not mean optimization, was just little bit surprised to have found it
– KumarAnkit
1 hour ago
|
show 5 more comments
6
Hard to tell from source code along, but it might just be a choice of the decompiler to show you this version. Note that a decompiler has to "guess" a bit - it chooses one possible source code that might lead to the given bytecode.
– Hulk
2 hours ago
2
@KumarAnkit - No necessarily optimization, no. There isn't a one-to-one relationship between source constructs and bytecode. That's what Hulk means when he/she says "a decompiler has to 'guess' a bit."
– T.J. Crowder
1 hour ago
4
@KumarAnkit what people are trying to explain is that maybe there's no optimization at all. Try translating a hindi (or whatever is your regional dialect) sentence in english using Google translate, and then back to hindi. You'll be lucky if it's the same sentence than at the beginning. Here it's the same thing, got it?
– Dici
1 hour ago
5
@KumarAnkit -for
(andwhile
, etc.) don't exist at the bytecode level. It's jump instructions, assignments, etc. One decompiler might look at some bytecode and say "that looks like afor
" while another might look at it and say "that looks like awhile
". "So, does it mean these loops are identical at the byte-code level?" Not necessarily. If you compile the code output by a decompiler, you don't necessarily end up with identical bytecode. In fact, I suspect you rarely would.
– T.J. Crowder
1 hour ago
1
@dici, thanks, I can understand this language as well. I got that it does not mean optimization, was just little bit surprised to have found it
– KumarAnkit
1 hour ago
6
6
Hard to tell from source code along, but it might just be a choice of the decompiler to show you this version. Note that a decompiler has to "guess" a bit - it chooses one possible source code that might lead to the given bytecode.
– Hulk
2 hours ago
Hard to tell from source code along, but it might just be a choice of the decompiler to show you this version. Note that a decompiler has to "guess" a bit - it chooses one possible source code that might lead to the given bytecode.
– Hulk
2 hours ago
2
2
@KumarAnkit - No necessarily optimization, no. There isn't a one-to-one relationship between source constructs and bytecode. That's what Hulk means when he/she says "a decompiler has to 'guess' a bit."
– T.J. Crowder
1 hour ago
@KumarAnkit - No necessarily optimization, no. There isn't a one-to-one relationship between source constructs and bytecode. That's what Hulk means when he/she says "a decompiler has to 'guess' a bit."
– T.J. Crowder
1 hour ago
4
4
@KumarAnkit what people are trying to explain is that maybe there's no optimization at all. Try translating a hindi (or whatever is your regional dialect) sentence in english using Google translate, and then back to hindi. You'll be lucky if it's the same sentence than at the beginning. Here it's the same thing, got it?
– Dici
1 hour ago
@KumarAnkit what people are trying to explain is that maybe there's no optimization at all. Try translating a hindi (or whatever is your regional dialect) sentence in english using Google translate, and then back to hindi. You'll be lucky if it's the same sentence than at the beginning. Here it's the same thing, got it?
– Dici
1 hour ago
5
5
@KumarAnkit -
for
(and while
, etc.) don't exist at the bytecode level. It's jump instructions, assignments, etc. One decompiler might look at some bytecode and say "that looks like a for
" while another might look at it and say "that looks like a while
". "So, does it mean these loops are identical at the byte-code level?" Not necessarily. If you compile the code output by a decompiler, you don't necessarily end up with identical bytecode. In fact, I suspect you rarely would.– T.J. Crowder
1 hour ago
@KumarAnkit -
for
(and while
, etc.) don't exist at the bytecode level. It's jump instructions, assignments, etc. One decompiler might look at some bytecode and say "that looks like a for
" while another might look at it and say "that looks like a while
". "So, does it mean these loops are identical at the byte-code level?" Not necessarily. If you compile the code output by a decompiler, you don't necessarily end up with identical bytecode. In fact, I suspect you rarely would.– T.J. Crowder
1 hour ago
1
1
@dici, thanks, I can understand this language as well. I got that it does not mean optimization, was just little bit surprised to have found it
– KumarAnkit
1 hour ago
@dici, thanks, I can understand this language as well. I got that it does not mean optimization, was just little bit surprised to have found it
– KumarAnkit
1 hour ago
|
show 5 more comments
4 Answers
4
active
oldest
votes
up vote
4
down vote
In this situation changing "while" to "for" is not an optimization. There is simply no way to know from byte code which one was used in a source code.
There are many situations when:
while(x)
is the same as:
for(;x;)
1
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
3
down vote
Both the for
loop and the while
loop code segments can be translated into similar machine code. After that when de-compiling the de-compiler has to pick one of the two possible
scenarios.
I guess that is what's happening here.
simply:
compile(A) -> C
compile(B) -> C
So when you are given C
, then there should be a guess to pick A
or B
4
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
1
down vote
As others have already pointed out: The decompiler (usually) cannot distinguish between different source codes that result in the same byte code.
Unfortunately, you did not provide the full code of the method. So the following contains some guesses about where and how this loop appears inside a method (and these guesses might, to some extent, distort the result).
But let's have a look at some roundtrips here. Consider the following class, containing methods with both versions of the code that you posted:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Pattern;
public class DecompileExample {
public static void methodA(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
String colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
}
}
Compiling it with
javac DecompileExample.java -g:none
will create the corresponding class file. (Note: The -g:none
parameter will cause the compiler to omit all debug information. The debug information might otherwise be used by the decompiler to reconstruct a more verbatim version of the original code, particularly, including the original variable names)
Now looking at the byte code of both methods, with
javap -c DecompileExample.class
will yield the following:
public static void methodA(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aload_0
5: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
8: dup
9: astore_1
10: ifnull 61
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #4 // class java/lang/StringBuilder
19: dup
20: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
23: ldc #6 // String line:
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: aload_1
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: iload_2
39: ifne 55
42: aload_1
43: ldc #10 // String |
45: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
48: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
51: astore_3
52: goto 4
55: iinc 2, 1
58: goto 4
61: return
and
public static void methodB(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aconst_null
5: astore_3
6: aload_0
7: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
10: dup
11: astore_1
12: ifnull 60
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: new #4 // class java/lang/StringBuilder
21: dup
22: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
25: ldc #6 // String line:
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: iload_2
41: ifne 54
44: aload_1
45: ldc #10 // String |
47: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
50: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
53: astore_3
54: iinc 2, 1
57: goto 6
60: return
}
(There is a small difference: The String colArr = null
is translated into an
aconst null
astore_3
at the beginning of the second version. But this is one of the aspects that is related to parts of the code that you have omitted in the question).
You did not mention which one you are using, but the JD-GUI decompiler from http://jd.benow.ca/ decompiles this into the following:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Pattern;
public class DecompileExample
{
public static void methodA(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
String arrayOfString = str.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
String arrayOfString = null;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
arrayOfString = str.split(Pattern.quote("|"));
}
i++;
}
}
}
You can see that the code is the same for both cases (at least regarding the loop - there one more is a difference regarding the "dummy variables" that I had to introduce in order to compile it, but this is unrelated to the question, so to speak).
The tl;dr message is clear:
Different source codes can be compiled into the same byte code. Consequently, the same byte code can be decompiled into different source codes. But every decompiler has to settle for one version of the source code.
(A side note: I was a bit surprised to see that when not compiling without -g:none
(that is, when the debug information is retained), JD-GUI even somehow manages to reconstruct that the first one used a while
-loop and the second one used a for
-loop. But in general, and when the debug information is omitted, this is simply no longer possible).
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
@KumarAnkit As indicated by the comments about the-g:none
flag, the result does not only depend on the decompiler, but also on how the.class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)
– Marco13
8 mins ago
add a comment |
up vote
1
down vote
That's basically because of the nature of bytecode. Java bytecode is something like assembly language, so there are no such things as for and while loop, there is simply jump instruction: goto. So there may be no difference between while and for loop, Both can be compiled to similar code and decompiler is just making guess.
3
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53778436%2fwhy-is-this-loop-changed%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
In this situation changing "while" to "for" is not an optimization. There is simply no way to know from byte code which one was used in a source code.
There are many situations when:
while(x)
is the same as:
for(;x;)
1
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
4
down vote
In this situation changing "while" to "for" is not an optimization. There is simply no way to know from byte code which one was used in a source code.
There are many situations when:
while(x)
is the same as:
for(;x;)
1
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
4
down vote
up vote
4
down vote
In this situation changing "while" to "for" is not an optimization. There is simply no way to know from byte code which one was used in a source code.
There are many situations when:
while(x)
is the same as:
for(;x;)
In this situation changing "while" to "for" is not an optimization. There is simply no way to know from byte code which one was used in a source code.
There are many situations when:
while(x)
is the same as:
for(;x;)
answered 1 hour ago
dgebert
31628
31628
1
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
1
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
1
1
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
3
down vote
Both the for
loop and the while
loop code segments can be translated into similar machine code. After that when de-compiling the de-compiler has to pick one of the two possible
scenarios.
I guess that is what's happening here.
simply:
compile(A) -> C
compile(B) -> C
So when you are given C
, then there should be a guess to pick A
or B
4
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
3
down vote
Both the for
loop and the while
loop code segments can be translated into similar machine code. After that when de-compiling the de-compiler has to pick one of the two possible
scenarios.
I guess that is what's happening here.
simply:
compile(A) -> C
compile(B) -> C
So when you are given C
, then there should be a guess to pick A
or B
4
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
3
down vote
up vote
3
down vote
Both the for
loop and the while
loop code segments can be translated into similar machine code. After that when de-compiling the de-compiler has to pick one of the two possible
scenarios.
I guess that is what's happening here.
simply:
compile(A) -> C
compile(B) -> C
So when you are given C
, then there should be a guess to pick A
or B
Both the for
loop and the while
loop code segments can be translated into similar machine code. After that when de-compiling the de-compiler has to pick one of the two possible
scenarios.
I guess that is what's happening here.
simply:
compile(A) -> C
compile(B) -> C
So when you are given C
, then there should be a guess to pick A
or B
edited 1 hour ago
meowgoesthedog
8,8033925
8,8033925
answered 1 hour ago
prime
4,56964073
4,56964073
4
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
4
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
4
4
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
Maybe you could put the actual bytecode of both snippets in your answer to prove your point :p it's the intuitive answer, but it doesn't mean it's right
– Dici
1 hour ago
add a comment |
up vote
1
down vote
As others have already pointed out: The decompiler (usually) cannot distinguish between different source codes that result in the same byte code.
Unfortunately, you did not provide the full code of the method. So the following contains some guesses about where and how this loop appears inside a method (and these guesses might, to some extent, distort the result).
But let's have a look at some roundtrips here. Consider the following class, containing methods with both versions of the code that you posted:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Pattern;
public class DecompileExample {
public static void methodA(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
String colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
}
}
Compiling it with
javac DecompileExample.java -g:none
will create the corresponding class file. (Note: The -g:none
parameter will cause the compiler to omit all debug information. The debug information might otherwise be used by the decompiler to reconstruct a more verbatim version of the original code, particularly, including the original variable names)
Now looking at the byte code of both methods, with
javap -c DecompileExample.class
will yield the following:
public static void methodA(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aload_0
5: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
8: dup
9: astore_1
10: ifnull 61
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #4 // class java/lang/StringBuilder
19: dup
20: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
23: ldc #6 // String line:
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: aload_1
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: iload_2
39: ifne 55
42: aload_1
43: ldc #10 // String |
45: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
48: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
51: astore_3
52: goto 4
55: iinc 2, 1
58: goto 4
61: return
and
public static void methodB(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aconst_null
5: astore_3
6: aload_0
7: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
10: dup
11: astore_1
12: ifnull 60
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: new #4 // class java/lang/StringBuilder
21: dup
22: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
25: ldc #6 // String line:
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: iload_2
41: ifne 54
44: aload_1
45: ldc #10 // String |
47: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
50: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
53: astore_3
54: iinc 2, 1
57: goto 6
60: return
}
(There is a small difference: The String colArr = null
is translated into an
aconst null
astore_3
at the beginning of the second version. But this is one of the aspects that is related to parts of the code that you have omitted in the question).
You did not mention which one you are using, but the JD-GUI decompiler from http://jd.benow.ca/ decompiles this into the following:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Pattern;
public class DecompileExample
{
public static void methodA(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
String arrayOfString = str.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
String arrayOfString = null;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
arrayOfString = str.split(Pattern.quote("|"));
}
i++;
}
}
}
You can see that the code is the same for both cases (at least regarding the loop - there one more is a difference regarding the "dummy variables" that I had to introduce in order to compile it, but this is unrelated to the question, so to speak).
The tl;dr message is clear:
Different source codes can be compiled into the same byte code. Consequently, the same byte code can be decompiled into different source codes. But every decompiler has to settle for one version of the source code.
(A side note: I was a bit surprised to see that when not compiling without -g:none
(that is, when the debug information is retained), JD-GUI even somehow manages to reconstruct that the first one used a while
-loop and the second one used a for
-loop. But in general, and when the debug information is omitted, this is simply no longer possible).
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
@KumarAnkit As indicated by the comments about the-g:none
flag, the result does not only depend on the decompiler, but also on how the.class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)
– Marco13
8 mins ago
add a comment |
up vote
1
down vote
As others have already pointed out: The decompiler (usually) cannot distinguish between different source codes that result in the same byte code.
Unfortunately, you did not provide the full code of the method. So the following contains some guesses about where and how this loop appears inside a method (and these guesses might, to some extent, distort the result).
But let's have a look at some roundtrips here. Consider the following class, containing methods with both versions of the code that you posted:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Pattern;
public class DecompileExample {
public static void methodA(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
String colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
}
}
Compiling it with
javac DecompileExample.java -g:none
will create the corresponding class file. (Note: The -g:none
parameter will cause the compiler to omit all debug information. The debug information might otherwise be used by the decompiler to reconstruct a more verbatim version of the original code, particularly, including the original variable names)
Now looking at the byte code of both methods, with
javap -c DecompileExample.class
will yield the following:
public static void methodA(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aload_0
5: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
8: dup
9: astore_1
10: ifnull 61
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #4 // class java/lang/StringBuilder
19: dup
20: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
23: ldc #6 // String line:
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: aload_1
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: iload_2
39: ifne 55
42: aload_1
43: ldc #10 // String |
45: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
48: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
51: astore_3
52: goto 4
55: iinc 2, 1
58: goto 4
61: return
and
public static void methodB(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aconst_null
5: astore_3
6: aload_0
7: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
10: dup
11: astore_1
12: ifnull 60
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: new #4 // class java/lang/StringBuilder
21: dup
22: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
25: ldc #6 // String line:
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: iload_2
41: ifne 54
44: aload_1
45: ldc #10 // String |
47: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
50: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
53: astore_3
54: iinc 2, 1
57: goto 6
60: return
}
(There is a small difference: The String colArr = null
is translated into an
aconst null
astore_3
at the beginning of the second version. But this is one of the aspects that is related to parts of the code that you have omitted in the question).
You did not mention which one you are using, but the JD-GUI decompiler from http://jd.benow.ca/ decompiles this into the following:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Pattern;
public class DecompileExample
{
public static void methodA(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
String arrayOfString = str.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
String arrayOfString = null;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
arrayOfString = str.split(Pattern.quote("|"));
}
i++;
}
}
}
You can see that the code is the same for both cases (at least regarding the loop - there one more is a difference regarding the "dummy variables" that I had to introduce in order to compile it, but this is unrelated to the question, so to speak).
The tl;dr message is clear:
Different source codes can be compiled into the same byte code. Consequently, the same byte code can be decompiled into different source codes. But every decompiler has to settle for one version of the source code.
(A side note: I was a bit surprised to see that when not compiling without -g:none
(that is, when the debug information is retained), JD-GUI even somehow manages to reconstruct that the first one used a while
-loop and the second one used a for
-loop. But in general, and when the debug information is omitted, this is simply no longer possible).
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
@KumarAnkit As indicated by the comments about the-g:none
flag, the result does not only depend on the decompiler, but also on how the.class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)
– Marco13
8 mins ago
add a comment |
up vote
1
down vote
up vote
1
down vote
As others have already pointed out: The decompiler (usually) cannot distinguish between different source codes that result in the same byte code.
Unfortunately, you did not provide the full code of the method. So the following contains some guesses about where and how this loop appears inside a method (and these guesses might, to some extent, distort the result).
But let's have a look at some roundtrips here. Consider the following class, containing methods with both versions of the code that you posted:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Pattern;
public class DecompileExample {
public static void methodA(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
String colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
}
}
Compiling it with
javac DecompileExample.java -g:none
will create the corresponding class file. (Note: The -g:none
parameter will cause the compiler to omit all debug information. The debug information might otherwise be used by the decompiler to reconstruct a more verbatim version of the original code, particularly, including the original variable names)
Now looking at the byte code of both methods, with
javap -c DecompileExample.class
will yield the following:
public static void methodA(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aload_0
5: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
8: dup
9: astore_1
10: ifnull 61
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #4 // class java/lang/StringBuilder
19: dup
20: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
23: ldc #6 // String line:
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: aload_1
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: iload_2
39: ifne 55
42: aload_1
43: ldc #10 // String |
45: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
48: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
51: astore_3
52: goto 4
55: iinc 2, 1
58: goto 4
61: return
and
public static void methodB(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aconst_null
5: astore_3
6: aload_0
7: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
10: dup
11: astore_1
12: ifnull 60
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: new #4 // class java/lang/StringBuilder
21: dup
22: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
25: ldc #6 // String line:
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: iload_2
41: ifne 54
44: aload_1
45: ldc #10 // String |
47: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
50: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
53: astore_3
54: iinc 2, 1
57: goto 6
60: return
}
(There is a small difference: The String colArr = null
is translated into an
aconst null
astore_3
at the beginning of the second version. But this is one of the aspects that is related to parts of the code that you have omitted in the question).
You did not mention which one you are using, but the JD-GUI decompiler from http://jd.benow.ca/ decompiles this into the following:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Pattern;
public class DecompileExample
{
public static void methodA(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
String arrayOfString = str.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
String arrayOfString = null;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
arrayOfString = str.split(Pattern.quote("|"));
}
i++;
}
}
}
You can see that the code is the same for both cases (at least regarding the loop - there one more is a difference regarding the "dummy variables" that I had to introduce in order to compile it, but this is unrelated to the question, so to speak).
The tl;dr message is clear:
Different source codes can be compiled into the same byte code. Consequently, the same byte code can be decompiled into different source codes. But every decompiler has to settle for one version of the source code.
(A side note: I was a bit surprised to see that when not compiling without -g:none
(that is, when the debug information is retained), JD-GUI even somehow manages to reconstruct that the first one used a while
-loop and the second one used a for
-loop. But in general, and when the debug information is omitted, this is simply no longer possible).
As others have already pointed out: The decompiler (usually) cannot distinguish between different source codes that result in the same byte code.
Unfortunately, you did not provide the full code of the method. So the following contains some guesses about where and how this loop appears inside a method (and these guesses might, to some extent, distort the result).
But let's have a look at some roundtrips here. Consider the following class, containing methods with both versions of the code that you posted:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Pattern;
public class DecompileExample {
public static void methodA(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
while ((line = reader.readLine()) != null) {
System.out.println("line: " + line);
if (i == 0) {
String colArr = line.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader reader) throws IOException {
String line = null;
int i = 0;
for (String colArr = null; (line = reader.readLine()) != null; ++i) {
System.out.println("line: " + line);
if (i == 0) {
colArr = line.split(Pattern.quote("|"));
} else {
}
}
}
}
Compiling it with
javac DecompileExample.java -g:none
will create the corresponding class file. (Note: The -g:none
parameter will cause the compiler to omit all debug information. The debug information might otherwise be used by the decompiler to reconstruct a more verbatim version of the original code, particularly, including the original variable names)
Now looking at the byte code of both methods, with
javap -c DecompileExample.class
will yield the following:
public static void methodA(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aload_0
5: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
8: dup
9: astore_1
10: ifnull 61
13: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
16: new #4 // class java/lang/StringBuilder
19: dup
20: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
23: ldc #6 // String line:
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: aload_1
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
35: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
38: iload_2
39: ifne 55
42: aload_1
43: ldc #10 // String |
45: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
48: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
51: astore_3
52: goto 4
55: iinc 2, 1
58: goto 4
61: return
and
public static void methodB(java.io.BufferedReader) throws java.io.IOException;
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: aconst_null
5: astore_3
6: aload_0
7: invokevirtual #2 // Method java/io/BufferedReader.readLine:()Ljava/lang/String;
10: dup
11: astore_1
12: ifnull 60
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: new #4 // class java/lang/StringBuilder
21: dup
22: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
25: ldc #6 // String line:
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: aload_1
31: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
40: iload_2
41: ifne 54
44: aload_1
45: ldc #10 // String |
47: invokestatic #11 // Method java/util/regex/Pattern.quote:(Ljava/lang/String;)Ljava/lang/String;
50: invokevirtual #12 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
53: astore_3
54: iinc 2, 1
57: goto 6
60: return
}
(There is a small difference: The String colArr = null
is translated into an
aconst null
astore_3
at the beginning of the second version. But this is one of the aspects that is related to parts of the code that you have omitted in the question).
You did not mention which one you are using, but the JD-GUI decompiler from http://jd.benow.ca/ decompiles this into the following:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.regex.Pattern;
public class DecompileExample
{
public static void methodA(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
String arrayOfString = str.split(Pattern.quote("|"));
} else {
i++;
}
}
}
public static void methodB(BufferedReader paramBufferedReader)
throws IOException
{
String str = null;
int i = 0;
String arrayOfString = null;
while ((str = paramBufferedReader.readLine()) != null)
{
System.out.println("line: " + str);
if (i == 0) {
arrayOfString = str.split(Pattern.quote("|"));
}
i++;
}
}
}
You can see that the code is the same for both cases (at least regarding the loop - there one more is a difference regarding the "dummy variables" that I had to introduce in order to compile it, but this is unrelated to the question, so to speak).
The tl;dr message is clear:
Different source codes can be compiled into the same byte code. Consequently, the same byte code can be decompiled into different source codes. But every decompiler has to settle for one version of the source code.
(A side note: I was a bit surprised to see that when not compiling without -g:none
(that is, when the debug information is retained), JD-GUI even somehow manages to reconstruct that the first one used a while
-loop and the second one used a for
-loop. But in general, and when the debug information is omitted, this is simply no longer possible).
answered 20 mins ago
Marco13
41.6k854106
41.6k854106
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
@KumarAnkit As indicated by the comments about the-g:none
flag, the result does not only depend on the decompiler, but also on how the.class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)
– Marco13
8 mins ago
add a comment |
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
@KumarAnkit As indicated by the comments about the-g:none
flag, the result does not only depend on the decompiler, but also on how the.class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)
– Marco13
8 mins ago
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
I am using the IntelliJ IDEA, which uses the fernflower decompiler. Thanks for the elaborated answer.
– KumarAnkit
16 mins ago
@KumarAnkit As indicated by the comments about the
-g:none
flag, the result does not only depend on the decompiler, but also on how the .class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)– Marco13
8 mins ago
@KumarAnkit As indicated by the comments about the
-g:none
flag, the result does not only depend on the decompiler, but also on how the .class
files are generated in the first place. (But I assume that IDEs will usually not omit the debug information - in the end, they are basically intended for retaining it in order to use it in some nice debugger UI)– Marco13
8 mins ago
add a comment |
up vote
1
down vote
That's basically because of the nature of bytecode. Java bytecode is something like assembly language, so there are no such things as for and while loop, there is simply jump instruction: goto. So there may be no difference between while and for loop, Both can be compiled to similar code and decompiler is just making guess.
3
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
add a comment |
up vote
1
down vote
That's basically because of the nature of bytecode. Java bytecode is something like assembly language, so there are no such things as for and while loop, there is simply jump instruction: goto. So there may be no difference between while and for loop, Both can be compiled to similar code and decompiler is just making guess.
3
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
add a comment |
up vote
1
down vote
up vote
1
down vote
That's basically because of the nature of bytecode. Java bytecode is something like assembly language, so there are no such things as for and while loop, there is simply jump instruction: goto. So there may be no difference between while and for loop, Both can be compiled to similar code and decompiler is just making guess.
That's basically because of the nature of bytecode. Java bytecode is something like assembly language, so there are no such things as for and while loop, there is simply jump instruction: goto. So there may be no difference between while and for loop, Both can be compiled to similar code and decompiler is just making guess.
edited 4 mins ago
Danish Ali
7601816
7601816
answered 1 hour ago
Wojtek Mlodzianowski
15813
15813
3
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
add a comment |
3
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
3
3
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
While true, I think a good answer should make an analysis of the actual byte code. I don't have the motivation to do it now so I'll stick to comments, but just sayin'
– Dici
1 hour ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53778436%2fwhy-is-this-loop-changed%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
6
Hard to tell from source code along, but it might just be a choice of the decompiler to show you this version. Note that a decompiler has to "guess" a bit - it chooses one possible source code that might lead to the given bytecode.
– Hulk
2 hours ago
2
@KumarAnkit - No necessarily optimization, no. There isn't a one-to-one relationship between source constructs and bytecode. That's what Hulk means when he/she says "a decompiler has to 'guess' a bit."
– T.J. Crowder
1 hour ago
4
@KumarAnkit what people are trying to explain is that maybe there's no optimization at all. Try translating a hindi (or whatever is your regional dialect) sentence in english using Google translate, and then back to hindi. You'll be lucky if it's the same sentence than at the beginning. Here it's the same thing, got it?
– Dici
1 hour ago
5
@KumarAnkit -
for
(andwhile
, etc.) don't exist at the bytecode level. It's jump instructions, assignments, etc. One decompiler might look at some bytecode and say "that looks like afor
" while another might look at it and say "that looks like awhile
". "So, does it mean these loops are identical at the byte-code level?" Not necessarily. If you compile the code output by a decompiler, you don't necessarily end up with identical bytecode. In fact, I suspect you rarely would.– T.J. Crowder
1 hour ago
1
@dici, thanks, I can understand this language as well. I got that it does not mean optimization, was just little bit surprised to have found it
– KumarAnkit
1 hour ago