My first session of the day was by Markus Eisele. He grouped the bad practices in developing Java EE application into seven groups labeled by the seven deadly sins. Did you know that the SpongeBob animated movie characters were prototyped exactly following those sins (lust, gluttony, wrath, greed, envy, sloth and pride)? I didn’t J
So here is a list of some of those “smells” outlined by the speaker that we all should avoid in our projects:
- Avoid over-engineering: write interfaces only if you really need them (especially in Java EE apps)
- Don’t try to implement all the design patterns you read yesterday in the GoF book, etc.
- Living on the cutting edge might sound cool, but if you plan to sell something, make sure you don’t depend on 0.0.1-SNAPSHOT libraries or languages
- Minimize your build and deploy time. If your build takes one hour, that’s not good
- Try not to mix complex technologies in one application (Spring and Java EE for example)
- People are not resources, two junior developers do not make for one senior
- Don’t be lazy and constantly do refactoring and peer reviews
- Avoid vendor lock-ins if the specification does not cover something
“I can do it better!” Really?
(Hard) Core Java
Last year I visited Charles Nutter’s (a.k.a. the JRuby guy) session on JIT compiler optimizations and learned so many things about the nuts and bolts of what happens under the hood in the JVM. I even blogged about it. So this year I decided to go to both his talks: on invokedynamic and on the path from Java to assembly code. I must admit that I did not understand much of the things, but I will try to share what I got.
So, most of the people thought that the invokedynamic feature (and everything that JSR 292 brought) is there just to suite the dynamic languages on the JVM. Because they had to do all kinds of equilibristic in order to shoehorn into the Java virtual machine. Most of you who have developed in JRuby or Scala for example may have noticed the tons of anonymous inner classes generated in your classes directory. And this is just the tip of the iceberg. So definitely the invokedynamic helps a lot here. It adds several new things:
- A new (terminal) byte code instruction (not surprisingly called invokedynamic), besides invokevrtual, invokeinterface, invokestatic and invokespecial
- The method handles
- The bootstrap methods
Let’s look to the last two elements.
In a nutshell, method handles are a better way to call methods than with java.lang.reflect.Method. Not necessarily faster (or at least not before Java 7 update 40), but better. Essentially, MethodHandle is an object that points to a method of a certain class with certain name and certain parameters of certain MethodType. Besides invoking them, you can do things like inserting parameters, changing parameters, deciding whether to invoke the methods based on a guard condition and all other cool stuff that you would usually do with a byte code manipulation library. And everything gets optimized by the VM!
What is a bootstrap method? Whenever a compiler (not JIT, but rather javac, scalac, groovyc, etc.) decides that it should insert invokedynamic instruction, it adds there the address (in the constant pool of course) of a bootstrap method. This is a standard Java method, which acts as something like a factory that finally produces method handle and passes it to the VM.
This is how the Java 8 lambdas work (and that’s the only thing I got from the second session ;)). Whenever javac sees lambda expression, it inserts in the byte code the invokedynamic instruction that points to a [bootstrap] method in the LambdaFactory class (part of the JDK). The latter returns a method handle to method, generated again by javac, which body contains the lambda code itself.
It’s interesting to know the Java internals in order to see what javac and the JVM do for you. But don’t use that for optimizing your programs before you have fixed all the problems that a standard profiler can find. Which appear to be 99% of all the problems in a project.
Maven to Gradle migration
This was actually a BOF, which didn’t answer the question how, but rather why you should do that. And of course the reason “Because everybody says that Gradle is cool” is wrong and can create yet another Cargo cult. Another wrong answer is: “Because you write in Groovy and not in XML”. It’s not so hard to change Maven’s input format, but it will not fix its problems:
- It is hard to use in big projects (LinkedIn for example have 3600 modules): the build takes too long, can’t be easily parallelized, incremental build does not work properly
- In big projects the normal maven plugins and workflow does not suit you, so most of the time you need to customize the build. However, writing a new plugin is pain, so people prefer writing ant or python scripts
For most of the projects Gradle can convert the pom.xml to gradle.build file. No matter which path you prefer to do the migration: automatic or manual, the speakers advised that you write a test that check the output of the old build and compare it with that of the new approach.
Of course, as they stated, today it’s easy to hate Maven. But let’s not forget what it did for the industry: it introduced convention over configuration way before Ruby on Rails, it established the practice to have common project structure and is much more understandable than ant or make.
Here are some links to the previous blogs about this years JavaOne: