0

I have a class file named StaticInitializer.class which obfuscated successfully. When I have decompiled it I got following result where IDE gives an compiler error "Cannot return from within an initializer". Removing "return" statement solves the problem. But In fact What I want to know is that how obfuscated class file works properly if it has an return statement in static initializer.

Is there a mismatch between compiling and running phase of java files, that obfuscation detects and uses them as a way of obfuscation?

Decompiled code

public class StaticInitializer {


    static {

        int a=12;
        int b=34;
        return ;
    }

}

Edited: Following operation shows that obfuscated class file is compiled with jdk 1.5

javap -c StaticInitializer.class
major version: 49  

J2SE 8 = 52, J2SE 7 = 51, J2SE 6.0 = 50,

J2SE 5.0 = 49,

JDK 1.4 = 48, JDK 1.3 = 47, JDK 1.2 = 46, JDK 1.1 = 45

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Ahmet Karakaya
  • 9,899
  • 23
  • 86
  • 141
  • 2
    Decompilers aren't gods. They can make mistakes. – BackSlash Jun 20 '14 at 07:06
  • in previous versions of Java (until Java 7) it was possible to run an application by a static block instead of the main method. they removed all the 'tricks 'n hacks' you could perform to do so, maybe that has an influence on it. also: as BackSlash states: decompilers can make mistakes. most decompilers are several versions of Java old, not up to date with the latest restrictions, which is why it may have considered that return statement a valid statement. – Stultuske Jun 20 '14 at 07:06
  • 1
    @Stultuske You can still do it ([DEMO](http://ideone.com/REAXnL)), as a static block gets executed as the class gets called, ***before*** any other method. And even if you couldn't, a `return` in a `static` block is not a valid statement. – BackSlash Jun 20 '14 at 07:08
  • 1
    @BackSlash no, you can't. it is true that the static block will always be performed before the main method, but up until Java 7, you could run an entire application without a main method. you could use the static block as entry point, and perform a System.exit as last statement of the static block. that worked, but not anymore. this is not what the static block was meant for, so from Java 7, they made it impossible to use a static block like that. – Stultuske Jun 20 '14 at 07:10
  • I am using JDK 1.6 and it also gives an error – Ahmet Karakaya Jun 20 '14 at 07:11
  • @Stultuske No. You ***can't*** have a program without a main class (and a main method). You can compile it, but you'll not be able to run it. And this happens with ***every*** java version, not only the last one. And in ***every*** java version you can have a `static` block with a `System.exit(0)` killing the program before the `main` method executes. – BackSlash Jun 20 '14 at 07:14
  • 1
    @BackSlash: before Java 7, yes, it was very possible. http://stackoverflow.com/questions/7591064/how-do-java-programs-run-without-defining-the-main-method – Stultuske Jun 20 '14 at 07:18
  • I have tried to compiled StaticInitializer.java file witj JDK 1.5 , it also gives an error? So return statement inside static initializer is not valid in JDK 1.5 spec – Ahmet Karakaya Jun 20 '14 at 07:33
  • @BackSlash Read the last comment on the accepted answer on [this](https://stackoverflow.com/questions/8605137/printing-message-on-console-without-using-main-method) question. Stultuske is correct. – awksp Jun 20 '14 at 07:41
  • The *whole point* of an obfuscator is to prevent you successfully decompiling the byte code. I suggest you have discovered that the obfuscator was successful in this case. But what else would you expect? – Raedwald Jun 20 '14 at 10:33

2 Answers2

2

A decompiler is never 100% accurate, as there are multiple ways of programming any line of code. ALso JAD (When we say decompiler for Java, it is almost synonymous to JAD) does not support JDK 1.5 and later. It is no longer developed or maintained.

Also looking at the decompiled code its giving you error because,From Java 7 onwards, it looks for a main method before loading the class. This is a change from previous java versions and hence your static block is not executing. In previous versions, the behavior was that JRE used to look for main method post loading the class and after executing the static blocks. So it would work in previous versions but not in new versions of java. But since JAD is no longer maintained it might show you the obsolete code which was valid at once upon a time.

Mustafa sabir
  • 4,130
  • 1
  • 19
  • 28
1

But In fact What I want to know is that how obfuscated class file works properly if it has an return statement in static initializer.

Every method must return, including a static initializer. At the bytecode level, there is (and must be) a return opcode. For whatever reason, the decompiler you used did not omit the return statement when translating the bytecode back into Java code, and thus you end up with a return statement in a context where explicit returns are not allowed. This may have nothing to do with the fact that your class was obfuscated.

Interestingly, some decompilers (like Procyon) do not explicitly omit return statements from initializer blocks. It's not usually necessary, because they attempt to remove all redundant return statements. Since an explicit return is not allowed, a static initializer compiled from Java code should only ever contain a single return, and it is always redundant, and therefore always gets removed. An obfuscator could encourage invalid Java code to be generated by inserting new return opcodes in body.

Mike Strobel
  • 25,075
  • 57
  • 69