Java compiler can do magic

Sometimes moving a java compiled file can cause weird behavior for first sight, which can lead to headaches of developers. This happened to a bunch of developers when they had to copy compiled files to their server. The full story can be red here.

For understanding the problem, please, first consider the following two java object implementations:

public class TheStaticFinalString {
public static final String s = “orange”;
}

public class UserOfTheStaticFinalString {
public void PrintlnString() {
if (TheStaticFinalString.s.equals(“orange”)) {
System.out.println(“orange”);
} else if(TheStaticFinalString.s.equals(“apple”)){
System.out.println(“apple”);
} else{
System.out.println(“This is definitely not an orange neither an apple”);
}
}

public static void main(String[] args) {
new UserOfTheStaticFinalString().PrintlnString();
}
}

The undesired behavior can happen if you compile those two classes and then you copy only the  UserOfTheStaticFinalString.class to another folder with another version of TheStaticFinalString.class.

Situation A: when the new folder contains TheStaticFinalString.class which has s = “apple”
Result: if you run UserOfTheStaticFinalString (java UserOfTheStaticFinalString in cmd) then you’ll get the magic result “orange”

Situation B: when the new folder contains no TheStaticFinalString.class file at all.
Result: if you run UserOfTheStaticFinalString (java UserOfTheStaticFinalString in cmd) then you’ll get the magic result “orange”

You might think as i thought: in situation A the result should be “apple” and in situation B the result should be an error as the static final string does not exist at all.
Well, this is a mistake. Regarding to string s is static, it is a compile-time attribute instead of being connected to an instance of an object at runtime. Although adding only static modifier to the attribute s would not cause this result. (it would cause my original thoughts) Adding final and static together makes the variable “definition-ish”, which means when compiling the code that uses it, compiler burns in the value to the user class in to the code. In this specific situation the bytecode of UserOfTheStaticFinalString.class at line
”    if (TheStaticFinalString.s.equals(“orange”)) {”
will be
”    if (orange.equals(“orange”)) {“.
From this point you can take UserOfTheStaticFinalString.class anywhere in file system, it will lead you to the same result no matter there are any TheStaticFinalString.classes or not.

Magic, isn’t it? 😉

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: