Because Java bytecode can be very easily decompiled, there are tools that will obfuscate the code for you. The result is that it can still be decompiled, but the result is illegible to humans.
On the other hand, there are certain humans who can beat any program in obfuscating source code. Their code is to machine-obfuscated code like hand-optimized assembler to compiler output.
While automatic obfuscators try to strip any meaning from variable names, method names, packages etc., the real pros just use misleading names, outdated comments, the right patterns for the wrong problems, etc.
Can you make this more interesting by posting such a class, so that we might try to refactor it?
Here is a real-life example that will hopefully demonstrate just how potent HandObfuscatedCode can be:
class Thing { ... };No, a class called "Thing" is almost no cent better or worse than a class name "xuzsf" as generated by a obfuscating program. They both carry no meaning. The latter just gives you an additional hint that the code got obfuscated, but since you usually have more than one class in a system, this advantage will cease if you only have names such as 'Thing', 'Something', etc. (Note: Similar to 'Object', 'Thing' may be a very good class name).
But what if that class models a relation rather than a thing?-)
I have an entire class hierarchy rooted at 'abstract class Thing' - the classes represent types of, well, things in a virtual world (like rooms, people, doors), and since I'm programming in Java, using 'Object' as the base class is out of the question. I'd consider this sensible usage =)
''Real evil comes, when the names seem to speak to you. But they lie: A class 'truck' which really represents 'passenger cars'? A method 'getBalance()' which really returns the credit and alters some attributes on the way?
Balance? I thought you were about to talk about balancing the tires on your truck...I mean passenger car. :-)
Here is one real life example.....
protected void validateReferralID(String referralID) throws ValidationException? { this.mandatoryValidation(referralID, 31227); this.validate(referralID, 31228, this.REFERRAL_ID_LENGTH); this.checkForZeroAndNegative(referralID, 31228); }This use of indenting and multi-line statements once confused me into thinking the exception would be thrown if rs.next() was true. Note the use or "rs", "a" etc for variable names.:
if (rs.next()) return(a); throw new FinderException?("Account "+number+" not known");The same programmer came up with this gem:
import com.XXX.common.*;public interface Account extends EJBObject, AccountConstants? {The XXX is the organization changed to protect the guilty.
The bad news is that I am in line to support thousands of lines of code such as that!
With respect, this ain't nothing compared with disassembled code mangled by a good obfuscator :-) guess I took the page too literally! You are wrong. The bad thing about hand obfuscated code is that you don't know it is hand obfuscated. That makes it much more evil.
See almost any entry on http://www.ioccc.org
But that's not java bytecode :-)
This reminds me of the exercise 11.14.13 and 11.14.14 of TheCppProgrammingLanguage?. It says there:
13. Write a program that has been rendered unreadable through the use of operator overloading and macros. An idea: Define + to mean - and vice versa for INTs. Then, use a macro to define int to mean INT. Redefine popular functions using reference type arguments. Writing a few misleading comments can also create great confusion.
14. Swap your results of 11.14.13 with a friend. Without running it, figure out what your friend's program does. When you have completed this exercise, you'll know what to avoid.
How about
public Object get_properlyResult() {...They certainly must mean "get_propertyResult"... do they?
Or how about giving similar, but slightly different names to the same value in the database, the code that fetches it from the database, as a method parameter, as a local variable in that method, the name used to store it in the session properties, and the variable used to refer to it on the JSP page? I didn't invent this!
You think that's hand-obfucated code. You haven't done hand-obfucated code until the bytecode doesn't decompile and if the massage the decompiler to get it to decompile it won't work because you used one of the abilities of java bytecode that does not exist in java sourcecode.
Two of the abilities are monitors are actually recursive mutexes (and as far as I can tell may be unlocked from another thread than the locking one) and using nondeclared checked exceptions for flow control (not fixable if going through a stock interface that doesn't declare them).
Undoubtedly, CharlesSimonyi proved to be a master in HandObfuscatedCode by inventing the HungarianNotation.
You think, the examples given above are not really created by a professional human obfuscator? OK, you got us. Mostly they are just bad code, written by people who probably didn't find their code bad at all. So the creators are surely obfuscators, maybe human, but absolutely no professionals. They are unintentionally, unconsciously competent at HandObfuscatedCode, making you ask: YouThinkThatsCodeYoureWriting?
This page is ambiguous by design. People should be puzzled whether there really is such a crazy thing as people practicing HandObfuscatedCode. Please leave it that way, especially at the top of the page - it's funnier that way. And leave this note near the bottom by adding text above it - not below. That's become a hand-obfuscated comment - I expected I must be near the end.
public int getMax() ( if (0 == a.length) return 0; int m = a[0]; for (int i = 1; i < a.length; ++i) { if (m > a[i]) m = a[i]; } return m; }This is just an example of a bug, not HandObfuscatedCode.
I tried this in my current project as an experiment for obfuscating some classes that form the License API for my product. I reverted back because it became unmaintainable by myself. (Although I had added comments that show the real method names and comments that indicate a lot of actual working. But still, method names and variable names say much more than comments). So, my advice is : STAY AWAY FROM THIS. Use good obfuscators (that do not have any major bugs ;-)).
Here's a CeeLanguage example from where I work, from a nearly 7000-line long file:
[snip] #define QUAD_MAX 9 #define QUAD_UPPER_LEFT 0 #define QUAD_UPPER_MIDDLE 1 #define QUAD_UPPER_RIGHT 2 #define QUAD_MIDDLE_LEFT 3 #define QUAD_MIDDLE 4 #define QUAD_MIDDLE_RIGHT 5 #define QUAD_LOWER_LEFT 6 #define QUAD_LOWER_MIDDLE 7 #define QUAD_LOWER_RIGHT 8 [snip] static int x_quad = 1; static int y_quad = 1; static int prev_x_quad = 1; static int prev_y_quad = 1; [snip] static int quad_numbers[3][3] = { QUAD_LOWER_LEFT, QUAD_MIDDLE_LEFT, QUAD_UPPER_LEFT, QUAD_LOWER_MIDDLE, QUAD_MIDDLE, QUAD_UPPER_MIDDLE, QUAD_LOWER_RIGHT, QUAD_MIDDLE_RIGHT, QUAD_UPPER_RIGHT }; static int quad_angles[3][3] = { 225, 270, 315, 180, 0, 0, 135, 90, 45 }; static int quad_objects[3][3] = { 1, 1, 1, 1, 0, 1, 1, 1, 1 }; [snip]-- AnonymousCoward
Here's another example:
p_send_cmd->panspd = 80; p_send_cmd->panspd = 0x80; p_send_cmd->panspd = -80; p_send_cmd->panspd = 0x80;The above statements occurred at various places in a 100-line-long switch/if conglomeration. Notice that some of the numbers are hex and some are decimal. This is not a bug. A value of 0x80 means off. Values from 0x00 to 0x80 mean left (so they just "happen" to choose 80). Values from 0x80 to 0xFF mean right (so they just "happen" to choose -80). I think this is a fine example of a programmer going out of his way to make the next guy trip up (anti DefensiveProgramming?) [OffensiveProgramming?].
-- same AnonymousCoward
This reminds me of a famous CeeLanguage pattern:
int a[5]; a[0] = 40000; a[1] = 20000; a[2] = 10000; a[3] = 05000; a[4] = 02500;-- RolandIllig?
OK now that's bad code. Mixing decimal and octal constants.
See also: ObfuscatedCee, ObfuscatedPerl, ObfuscatedPgpInJavaScript