Tag Archives: java

Fun with manually diffing Java bytecode instructions

I recently found myself writing code against a simple library that was distributed in the form of a .class file. For a few reasons (laziness being one of them), I decompiled the class file using jd-gui and just added it to the source path of my project. Decompiling binary Java code and using it in a project is fairly routine and I’ve never had a problem with it before. This time, however, I noticed slightly anomalous behavior from the code.

Swapping it out with the binary version of the class fixed the problem, which was good, but left me wondering – why did the decompiled version behave slightly differently? Decompiling Java code is usually pretty safe, and if it had messed up, I’d expect a more immediate problem like a compilation failure. Intrigued, I decided to spend a few minutes figuring out just why decompiling a class and using the source to compile with had led to subtly different behavior.

Java Bytecode

One of the interesting things about Java is that the compiler (javac) doesn’t do very much optimization at all – code optimization occurs at runtime. The resulting bytecode – if deliberate obfuscation steps aren’t performed – can be easily decompiled and reassembled into Java code, and it is generally quite easy to manually read through to figure out what is going on. So, it seems like a reasonable place to start if we want to figure out why two pieces of nearly-identical code are behaving differently.

Bytecode Diffing

I’ll save you the tedium of poring through a few hundred lines of bytecode, and just show the interesting part. Here is the result from running javap -c on the original .class file:


108: iload 16
110: i2d
111: iload 17
113: i2d
114: ddiv
115: dstore 18

This is pretty simple – it takes the integer located in variable slot #16, putting it on the stack, then converting that value to a double, and placing it back on the stack. It does so for a second integer, then does double division and assigns the double result to variable slot #18. We can imagine the original Java code looked something like this:


double x = (double)y/(double)z;

What does it then do with x?


117: dload 5
119: dload 18
121: dcmpg
122: ifge 136

Again, fairly simple code – it is comparing two doubles and branching based on the result. We can imagine the original code looked something like this:


if(a < x){ .... }

Moving on to the code that has been decompiled (by jd-gui), recompiled with javac, then examined with javap -c, the problem is easy to find:


108: iload 16
110: iload 17
112: idiv
113: i2d
114: dstore 18

This might appear to be fairly similar, but there is an important difference. Here is what this block of code does: Push an int (#16) on to the stack. Push another int (#17) onto the stack. Perform integer division (which rounds the result to the integer closest to 0). Convert the integer to a double (i2d), then store the double in #18. The decompiled Java code looked something like this:


double x = y/z;

For any non-trivial piece of code, you'd have to get fairly lucky to spot this problem. For one, when we see this block of code, we don't actually know the types of y and z - and there could be a lot of trivial operations like this. Second, there are cases where rounding is perfectly valid.

This small bug led to the comparison behaving incorrectly in some cases (ie, if a = 2.0 and we compare what should be 2.5, they'll actually be equal due to rounding), which led to statistical anomalies in the output.

Decompiler Bugs

So, this is obviously a pretty simple decompiler bug. How did it happen? Well, remember when I told you that javac created bytecode that pretty closely mirrored the Java code? One of the small things it does is automatically insert primitive widening conversions - that is, it inserts bytecodes (such as i2d) to convert from one primitive type to another when it can guarantee that no loss of precision will occur. Integers to doubles are one of these cases, and you can see in our decompiled example how it automatically inserted an i2d call.

My guess is that some decompilers assume that all widening conversions (such as i2d) are automatically inserted by javac and can be safely elided from the decompiled code - probably to reduce the amount of noise in the code. However, it is quite clear that not all widening conversions are safe to ignore - thinking about it naively, it seems like there would be a set of rules you could follow to determine when it would be safe to ignore them and when it isn't, but I'm not convinced you could ever be 100% correct.

Conclusion

While there probably isn't a ton of useful technical information in this post, I had a lot of fun tracking the problem down - tracking down weird, seemingly impossible problems can be an enjoyable experience, and having some notion of what bytecode is and how it works can come in handy occasionally. This has, however, made me slightly more careful when using Java source code that has been decompiled from its class file format.

What is Oracle’s mobile strategy for Java?

It has been a tumultuous time for Java – the transition to Oracle ownership has been rocky, there has been JCP drama, the language is falling behind feature-wise, and it’s future on a increasingly important platform (OS X) was briefly looking bleak.

Oracle’s stewardship over Java has been the center of a lot of controversy lately, and at least some of it has been largely due to Oracle’s communication with the Java community. I think there is a bit of a culture shock for both sides in this transition – Oracle is used to tightly controlled, infrequent communication with developers, whereas the Java community is used to constant communication and openness from Sun.

I suspect over time this culture difference will become less of an issue – Oracle is already showing a little bit that they can learn to open up and communicate better, and I think the Java community will grow to accept Oracle’s communication style.

For me, however, there is a much more depressing situation going on with the Java platform right now – Oracle not only lacks a (public) vision for the future of Java on mobile devices, they are actively preventing others from making Java relevant in the mobile space through litigation and licensing terms.

First, where is Oracle taking Java in the mobile space? In my view, down a dead-end. At JavaOne, there was a lot of hype (as there was under Sun) about the number of mobile devices Java ran on. Unfortunately, JavaME lacks most of the appeal of the current generation of smart phone platforms – it lacks the features of iOS or Android, is more difficult to develop with, doesn’t target powerful smart phones, and has a much more involved deployment process. In my view, JavaME represents the past, and concentrating on past success isn’t a very good long-term strategy.

There is, however, a company doing interesting stuff with Java in the mobile space – Google. Android competes very well with iOS, is relatively pleasant to develop for, and has a good deployment model. It has its drawbacks, but it is far more interesting and relevant than JavaME. What does Oracle do? They sue Google.

Adding to this is the licensing spat with Apache Harmony over field-of-use restrictions in the TCK designed to prevent Harmony from being used in the mobile space. To be fair, this was an issue that Sun failed to resolve and wasn’t something that Oracle added in after acquiring Sun. To be less fair, when Oracle was just a member of the JCP and not the owner of Java, they strongly supported removing the field-of-use restriction – now that they situation has changed, however, they aren’t doing the very thing they originally supported.

So, to sum up my complaints as a member of the Java community – not only does Oracle (and to be fair, Sun before them) lack a coherent, interesting long-term mobile strategy, they are actively preventing others in the community for moving forward on their own. Will this kill Java? Doubtful – Java can remain viable and interesting without any sort of mobile presence. It certainly is missing a huge opportunity and it will be unfortunate if the millions of talented, motivated Java developers can’t apply their Java skills to developing compelling, useful mobile applications.

Analysis of Apple’s Java bombshell

I heard about Apple’s deprecation of Java just as I was headed to BlizzCon this week and have spent some time over the past few days chewing on Apple’s move, their motives, and the ramifications.

The sky isn’t falling… yet.

Java 6 is currently quite well-support on OS X. Java 7 isn’t slated to be released until mid-2011, and there is usually a lag between when a new version of Java is released and when people are able to start using it. Apple’s Java releases have historically lagged behind Sun’s releases – sometimes by over a year. This obviously isn’t a terribly good situation, but it does mean there is a significant amount of time to at least achieve “business as usual” for Java on OS X.

There is also one bit of good news in the release – it looks like Apple is trying to accomodate third-party JVMs.

Motives

There has been a ton of speculation about why Apple is making this move – from pure business reasons, to Apple wanting to kill Java, to Apple wanting even more control over their entire platform. If I had to guess, I’d say it is a combination of #1 and #3. Apple is clearly moving Mac OS closer to iOS, and Java doesn’t really have a place in that transition. Apple would rather use resources dedicated to maintaining Java for Mac OS to do something that is closer to their long-term goals. Unfortunately, I think Sun is partly to blame for this – poor marketing and poor focus on desktop Java has made it largely irrelevant except for developers, which makes it easy for Apple to ignore it.

Don’t take it personally

Apple isn’t very sentimental about technology and they have nowhere near the emphasis on backwards compatibility that other companies (like Sun or Microsoft) have. They are pretty ruthless about abandoning technology when they feel it no longer helps them meet their goals.

Apple can kind of get away with this a little more because the majority of the products they sell are consumer-related with an expected lifespan that is very short. It is also part of their culture, however, and I think it helps them be successful. Backwards compatibility is a double-edged sword, and while it hurts when you are on the wrong side of it, I think Apple does a decent job of balancing it.

Is Mac OS going to become iOS with a keyboard and better hardware?

Looking at Apple’s history and what they are doing with iOS, there is good reason to wonder this. I think Apple definitely wants to move Mac OS closer to the model for iOS – it gives them a ton of control (which they like because, among other things, it allows them to create a better experience for most users) and because it gets them more money (by controlling application distribution, they can get a cut of each sale).

That said, I have doubts as to how far they will be able to take this. For one, there are legal issues – I think Apple is already playing with anti-trust fire right now with iOS, and total control of the desktop situation would sure be attract unwanted attention from the DOJ. More importantly, there are pragmatic issues. Developers, creative professionals, and other power-users would have a hard time working with a a crippled, locked-down Mac OS that some people are envisioning.

Does Apple need Java?

Obviously, Java isn’t critical to Apple’s success, but it is (and will continue to be) important to them for a few reasons. First off, Apple themselves use Java quite a bit for their server-side stuff – the Apple Online Store, the iTunes backend, and other systems. They’ll need to have some level of Java support in OS X in order to continue to support these systems, but I’m not sure how they intend to handle that.

A Java-less Mac OS also hurts sales of Mac hardware – not enough to seriously hurt Apple, but enough to make me wonder how much financial sense it makes for them to discontinue their support for Java. Apple typically utilizes small, effective teams, and I don’t think the team that supports Java at Apple is more than a handful of people, which means it can’t cost them more than a few million dollars to maintain Java. Judging by the number of MacBook Pros at JavaOne alone, this seems like a pretty effective investment – unless Apple thinks someone else will maintain Java enough to keep Java developers interested.

Does Java need Apple?

Probably, to some degree. Apple is doing a great job marketing the Mac OS platform and I think it is reasonable to assume it will continue to grow. If Oracle is concerned about getting traction in the consumer market with Java, then making sure there is a good JVM for Mac OS is going to be really important. On the developer side of things, I think it is also important for there to be good Java support on the Mac. There is already quite a bit of uncertainty and negativity around Java right now – JCP shenanigans going on right now, Oracle’s lawsuit against Google, and concerns about the pace of new features and releases. Losing support for a major platform like Mac OS would be another blow to a community that is already a bit unsettled right now.

Oracle hasn’t really shown much interest in the Mac platform and it will be interesting to see if they are willing to devote resources to keeping Java alive on it.

Where do we go from here?

I don’t think Apple is doing anything particularly nefarious here, even though the result appears to be somewhat unfortunate in the short-term. I think there opportunities for Oracle and other big members of the Java community to step up and fill the void that Apple is leaving. Perhaps in the long-run, this ends up being good news for Java on Mac OS? Apple generally did a decent job of providing Java on Mac OS, except that it was always well behind other platforms and Apple is notoriously bad about communicating their plans for Java – perhaps someone else would do a better job?

More updates about the Oracle vs Google lawsuit

The text of Oracle’s complaint is available online, here (courtesy of Rick Ross of JavaLobby and dzone). It appears as though the complaint centers around 7 patents and a claim of copyright infringement.

Patents

There are 7 patent claims, all of which seem to center around virtual machine related concepts:

6,125,447 – Protection domains to provide security in a computer system
6,192,476 – Controlling access to a resource
5,966,702 – Method and apparatus for pre-processing and packaging class files
7,426,720 – System and method for dynamic preloading of classes through memory space cloning of a master runtime system process
RE38,104 – Method and apparatus for resolving data references in generated code
6,910,205 – Interpreting functions utilizing a hybrid of virtual and native machine
6,061,520 – Method and system for performing static initialization

Copyright

The complaint also references the copyrights around code, documentation, and other artifacts surrounding the Java platform, and claims Google infringes on some of these as well. It isn’t immediately clear what they are referring to, however.

What this means

It is pretty clear that this complaint is centered around the Dalvik VM. Lots of people (including me) have already been speculating about whether or not GWT could also find itself a target of Oracle lawsuits. It is probably safe from the patents listed above, but there is still a potential of it having the same copyright violations as Android – or perhaps Oracle has more patents up its sleeve.

Further, people have been suggesting that Google change Android to use one of the alternate JVM languages (such as Scala or Clojure) instead of Java, but it is unlikely that would make a difference, since the complaint centers around the VM.

The reaction from the Java community has been swift and negative towards Oracle. Google is doing some cool and innovative stuff with Java, why is Oracle going after them like this? Google has been hugely involved with Java, will this lawsuit push them towards another language/platform?

Oracle sues Google over Android

I recall a few years back when rumors were swirling about potential buyers of Sun Microsystems. There seemed to be a consensus within the Java community that it would be better for the future of Java for Sun to be acquired by Oracle rather than IBM. Oracle had been a good participant in the JCP and didn’t have as much direct reliance on Java for their business, and thus would have less incentive to muck around with Java.

Today, however, I think much of that goodwill evaporated. According to MSNBC, Oracle is suing Google, claiming that Android violates numerous Java-related patents. I think this doesn’t bode well for the long-term outlook for Java.

Android

Android is one of the most exciting areas in Java development today – it is standing toe-to-toe with Apple’s iOS in the hottest technology space (mobile). JavaME has been reasonably successful – more so than people often give it credit for – but it can’t compete with iOS or any of the other smartphone platforms. Without Android, Java has limited representation in the mobile market.

Frankly, I’m confused as to why Oracle is going after Google here – a consumer phone OS seems pretty far out the realm of Oracle’s normal business.

GWT

I hadn’t even thought of this until one of my co-workers pointed it out – GWT has some of the same legal issues in this case as Android and could fall into Oracle’s crosshairs as well. Oracle has been incredibly excited about JavaFX and GWT is a direct competitor in that area. Will Oracle go after GWT next?

What else?

Java is an excellent language, but it has been showing its age for some time now. Many other languages offer more advanced features and are arguably better in some areas (C# comes to mind), but the main strengths that have kept Java relevant for so long have been the JVM and the community around the platform. If Oracle goes around suing everyone in the Java community with their new IP assets, what does that mean for the community?

Ultimately, we’ll have to see how this develops and what happens – perhaps they will settle quickly, with Google paying some licensing fees and Oracle leaving everyone else alone. Or, perhaps this is just the beginning of Oracle milking every dollar they can out of the Java platform.

With this development, plus all of the high-profile departures of ex-Sun employees, I’m a little worried about the long-term future of the Java platform under the stewardship of Oracle.