Why is this loop changed?











up vote
12
down vote

favorite
1












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?










share|improve this question




















  • 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 (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




    @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















up vote
12
down vote

favorite
1












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?










share|improve this question




















  • 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 (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




    @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













up vote
12
down vote

favorite
1









up vote
12
down vote

favorite
1






1





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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 (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




    @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




    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 (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




    @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












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;)





share|improve this answer

















  • 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


















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






share|improve this answer



















  • 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


















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).






share|improve this answer





















  • 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


















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.






share|improve this answer



















  • 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











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
});


}
});














draft saved

draft discarded


















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;)





share|improve this answer

















  • 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















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;)





share|improve this answer

















  • 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













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;)





share|improve this answer












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;)






share|improve this answer












share|improve this answer



share|improve this answer










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














  • 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












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






share|improve this answer



















  • 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















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






share|improve this answer



















  • 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













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






share|improve this answer














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







share|improve this answer














share|improve this answer



share|improve this answer








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














  • 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










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).






share|improve this answer





















  • 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















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).






share|improve this answer





















  • 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













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).






share|improve this answer












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).







share|improve this answer












share|improve this answer



share|improve this answer










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


















  • 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










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.






share|improve this answer



















  • 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















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.






share|improve this answer



















  • 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













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.






share|improve this answer














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.







share|improve this answer














share|improve this answer



share|improve this answer








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














  • 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


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

Mangá

 ⁒  ․,‪⁊‑⁙ ⁖, ⁇‒※‌, †,⁖‗‌⁝    ‾‸⁘,‖⁔⁣,⁂‾
”‑,‥–,‬ ,⁀‹⁋‴⁑ ‒ ,‴⁋”‼ ⁨,‷⁔„ ‰′,‐‚ ‥‡‎“‷⁃⁨⁅⁣,⁔
⁇‘⁔⁡⁏⁌⁡‿‶‏⁨ ⁣⁕⁖⁨⁩⁥‽⁀  ‴‬⁜‟ ⁃‣‧⁕‮ …‍⁨‴ ⁩,⁚⁖‫ ,‵ ⁀,‮⁝‣‣ ⁑  ⁂– ․, ‾‽ ‏⁁“⁗‸ ‾… ‹‡⁌⁎‸‘ ‡⁏⁌‪ ‵⁛ ‎⁨ ―⁦⁤⁄⁕