Posts Tagged ‘JVM’
  • Synthetic

    Plastic straw tubes

    :page-liquid: :icons: font :experimental:

    There is a bunch of languages running on the JVM, from of course[Java^], to[Clojure^] and[JRuby^]. All of them have different syntaxes, but it’s awesome they all compile to the same bytecode. The JVM unites them all. Of course, it’s biased toward Java, but even in Java, there is some magic happening in the bytecode.

    The most well-known trick comes from the following code:


    public class Foo { static class Bar { private Bar() {} }

    public static void main(String... args) {
        new Bar();
    } } ----

    Can you guess how many constructors the Bar class has?

    Two. Yes, you read that well. For the JVM, the Bar class declares 2 constructors. Run the following code if you don’t believe it:


    Class clazz = Foo.Bar.class; Constructor<?>[] constructors = clazz.getDeclaredConstructors(); System.out.println(constructors.length); -> { System.out.println("Constructor: " + constructor); }); ----

    The output is the following:

    Constructor: private Foo$Bar() Constructor: Foo$Bar(Foo$1) —-

    The reason is[pretty well documented^]. The bytecode knows about access modifiers, but not about nested classes. In order for the Foo class to be able to create new Bar instances, the Java compiler generates an additional constructor with a default package visibility.

    This can be confirmed with the javap tool.

    [source,bash] javap -v out/production/synthetic/Foo$Bar.class

    This outputs the following:

    […] { Foo$Bar(Foo$1); descriptor: (LFoo$1;)V flags: ACC_SYNTHETIC Code: stack=1, locals=2, args_size=2 0: aload_0 1: invokespecial #1 // Method “":()V 4: return LineNumberTable: line 2: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LFoo$Bar; 0 5 1 x0 LFoo$1; } [...] ----

    Notice the ACC_SYNTHETIC flag. Going to the JVM specifications yields the following information:

    [quote, The class File Format,] The ACC_SYNTHETIC flag indicates that this method was generated by a compiler and does not appear in source code, unless it is one of the methods named in §4.7.8.


    Theoretically, it should be possible to call this generated constructor - notwithstanding the fact that it’s not possible to provide an instance of Foo$1, but let’s put it aside. But the IDE doesn’t seem to be able to discover this second non-argumentless constructor. I didn’t find any reference in the[Java Language Specification^], but synthetic classes and members cannot be accessed directly but only through reflection. ====

    At this point, one could wonder why all the fuss about the synthetic flag. It was introduced in Java to resolve the issue of nested classes access. But other JVM languages use it to implement their specification. For example, Kotlin uses synthetic to access the companion object:


    class Baz() { companion object { val BAZ = “baz” } } —-

    Executing javap on the .class file returns the following output (abridged for readability purpose) :

    { public static final Baz$Companion Companion; descriptor: LBaz$Companion; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

    public Baz(); […]

    public static final java.lang.String access$getBAZ$cp(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC Code: stack=1, locals=0, args_size=0 0: getstatic #22 // Field BAZ:Ljava/lang/String; 3: areturn LineNumberTable: line 1: 0 RuntimeInvisibleAnnotations: 0: #15() } […] —-

    Notice the access$getBAZ$cp() static method? That’s the name of the method that should be called from Java:


    public class FromJava {

    public static void main(String... args) {
    } } ----

    == Conclusion

    While knowledge of the synthetic flag is not required in the day-to-day work of a JVM developer, it can be helpful to understand some of the results returned by the reflection API.

    Categories: Java Tags: JVMbytecodejavapKotlin
  • Signing and verifying a standalone JAR


    :revdate: 2017-02-05 16:00:00 +0100 :page-liquid: :icons: font :experimental:

    link:{% post_url 2017-02-05-proposal-java-policy-files-crafting-process %}[Last week^], I wrote about the JVM policy file that explicitly lists allowed sensitive API calls when running the JVM in sandboxed mode. This week, I’d like to improve the security by signing the JAR.

    == The nominal way

    This way doesn’t work. Readers more interested in the solution than the process should skip it. **

    === Create a keystore

    The initial step is to create a keystore if none is already available. There are plenty of online tutorials showing how to do that.


    keytool -genkey -keyalg RSA -alias selfsigned -keystore /path/to/keystore.jks -storepass password -validity 360 —-

    Fill in information accordingly.

    === Sign the application JAR

    Signing the application JAR must be part of the build process. With Maven, the[JAR signer plugin^] is dedicated to that. Its usage is quite straightforward:


    maven-jarsigner-plugin 1.4 sign sign /path/to/keystore.jks selfsigned ${store.password} ${key.password}

    To create the JAR, invoke the usual command-line and pass both passwords as system properties:


    mvn package -Dstore.password=password -Dkey.password=password —-

    Alternatively, Maven’s[encryption capabilities^] can be used to store passwords in a dedicated settings-security.xml to further improve security.

    === Configure the policy file

    Once the JAR is signed, the policy file can be updated to make use of it. This requires only the following configuration steps:

    1. Point to the keystore
    2. Configure the allowed alias


    keystore “keystore.jks”;

    grant signedBy “selfsigned” codeBase “file:target/spring-petclinic-1.4.2.jar” { … } —-

    Notice the signedBy keyword followed by the alias name - the same one as in the keystore above.

    === Launching the JAR with the policy file

    The same launch command can be used without any change:


    java -jar target/spring-petclinic-1.4.2.jar —-

    Unfortunately, it doesn’t work though this particular permission had already been configured!


    Caused by: access denied (“java.lang.reflect.ReflectPermission” “suppressAccessChecks”) at at at java.lang.SecurityManager.checkPermission( at java.lang.reflect.AccessibleObject.setAccessible( at org.springframework.util.ReflectionUtils.makeAccessible( at org.springframework.beans.BeanUtils.instantiateClass( at org.springframework.boot.SpringApplication.createSpringFactoriesInstances( —-

    The strangest part is that permissions requested before this one work all right. The reason is to be found in the particular structure of the JAR created by the Spring Boot plugin: JAR dependencies are packaged untouched in a BOOT-INF/lib folder in the executable JAR. Then Spring Boot code uses custom class-loading magic to load required classes from there.

    JAR signing works by creating a specific hash for each class, and by writing them into the JAR manifest file. During the verification phase, the hash of a class is computed and compared to the hash of the manifest. Hence, permissions related to classes located in the BOOT-INF/classes folder work as expected.

    However, the org.springframework.boot.SpringApplication class mentioned in the stack trace above is part of the spring-boot.jar located under BOOT-INF/lib: verification fails as there’s no hash available for the class in the manifest.

    Thus, usage of the Spring Boot plugin for JAR creation/launch is not compatible with JAR signing.

    == The workaround

    Aside from Spring Boot, there’s a legacy way to create standalone JARs: the[Maven Shade plugin^]. This will extract every class of every dependency in the final JAR. This is possible with Spring Boot apps, but it requires some slight changes to the POM:

    1. In the POM, remove the Spring Boot Maven plugin
    2. Configure the main class in the Maven JAR plugin: + [source,xml] —-
    maven-jar-plugin 3.0.2 org.springframework.samples.petclinic.PetClinicApplication
    1. Finally, add the Maven Shade plugin to work its magic: + [source,xml] —-
    maven-shade-plugin 2.4.3 true package shade

    WARNING: The command-line to launch the JAR doesn’t change but permissions depend on the executed code, coupled to the JAR structure. Hence, the policy file should be slightly modified.

    == Lessons learned

    While it requires to be a little creative, it’s entirely possible to sign Spring Boot JARs by using the same techniques as for any other JARs.

    To go further:

    •[Jarsigner Plugin^]
    •[Shade Plugin^]
    •[Spring Boot plugin^]
    •[Spring Boot executable JAR format^]
    Categories: Java Tags: JVMsecurityJARSpring Bootpolicy
  • Proposal for a Java policy files crafting process

    Security guy on an escalator

    :revdate: 2017-02-05 16:00:00 +0100 :page-liquid: :icons: font :experimental:

    I’ve link:{% post_url 2016-01-17-java-security-manager %}[already^] link:{% post_url 2017-01-29-compilation-java-code-on-the-fly %}[written] about the JVM security manager, and why it should be used - despite it being rarely the case, if ever. However, just advocating for it won’t change the harsh reality unless some guidelines are provided to do so. This post has the ambition to be the basis of such guidelines.

    As a reminder, the JVM can run in two different modes, standard and sandboxed. In the former, all API are available with no restriction; in the later, some API calls deemed sensitive are forbidden. In that case, explicit permissions to allow some of those calls can be configured in a dedicated policy file.

    NOTE: Though running the JVM in sandbox mode is important, it doesn’t stop there .e.g. executing only digitally-signed code is also part of securing the JVM. This post is the first in a 2 parts-serie regarding JVM security.

    == Description

    The process is based on the[principle of least privilege^]. That directly translates into the following process:

    1. Start with a blank policy file
    2. Run the application
    3. Check the thrown security exception
    4. Add the smallest-grained permission possible in the policy file that allows to pass step 2
    5. Return to step 2 until the application can be run normally

    Relevant system properties include:

    • activates the Java Security manager
    • points to the desired policy file
    • last but not least, activates debugging information when an absent privilege is required. There are a ton of[options^].

    That sounds easy enough but let’s go detail how it works with an example.

    == A case study

    As a sample application, we will be using the[Spring Pet Clinic^], a typical albeit small-sized Spring Boot application.

    === First steps

    Once the application has been built, launch it with the security manager:


    java -jar target/spring-petclinic-1.4.2.jar —-

    This, of course, fails. The output is the following:

    Exception in thread “main” java.lang.IllegalStateException: access denied (“java.lang.RuntimePermission” “getProtectionDomain”) at org.springframework.boot.loader.ExecutableArchiveLauncher.( at org.springframework.boot.loader.JarLauncher.( at org.springframework.boot.loader.JarLauncher.main( Caused by: access denied ("java.lang.RuntimePermission" "getProtectionDomain") at at at java.lang.SecurityManager.checkPermission( at java.lang.Class.getProtectionDomain( at org.springframework.boot.loader.Launcher.createArchive( at org.springframework.boot.loader.ExecutableArchiveLauncher.( ... 2 more ----

    Let’s add the permission relevant to the above “access denied” exception to the policy file:


    grant codeBase “file:target/spring-petclinic-1.4.2.jar” { permission java.lang.RuntimePermission “getProtectionDomain”; }; —-

    Notice the path pointing to the JAR. It prevents other potentially malicious archives to execute critical code. Onto the next blocker.

    Exception in thread “main” access denied (“java.util.PropertyPermission” “java.protocol.handler.pkgs” “read”) —-

    This can be fixed by adding the below line to the policy file:


    grant codeBase “file:target/spring-petclinic-1.4.2.jar” { permission java.lang.RuntimePermission “getProtectionDomain”; permission java.util.PropertyPermission “java.protocol.handler.pkgs”, “read”; }; —-

    Next please.

    Exception in thread “main” access denied (“java.util.PropertyPermission” “java.protocol.handler.pkgs” “read”) —-

    Looks quite similar, but it needs a write permission in addition to the read one. Sure it can be fixed by adding one more line, but there’s a shortcut available. Just specify all necessary attributes of the permission on the same line:


    grant codeBase “file:target/spring-petclinic-1.4.2.jar” { permission java.lang.RuntimePermission “getProtectionDomain”; permission java.util.PropertyPermission “java.protocol.handler.pkgs”, “read,write”; }; —-

    Rinse and repeat. Without further ado, the (nearly) final policy can be found[online^]: a whooping ~1800 lines of configuration for the Spring Boot Pet Clinic as an executable JAR.

    Now that the general approach has been explained, it just needs to be followed until the application functions properly. The next section describe some specific glitches along the way.

    === Securing Java logging

    At some point, nothing gets printed in the console anymore. The command-line just returns, that’s it. Comes the system property - described above, that helps resolve the issue:


    java,stacktrace -jar target/spring-petclinic-1.4.2.jar —-

    That yields the following stack:

    java.lang.Exception: Stack trace at java.lang.Thread.dumpStack( at at at java.lang.SecurityManager.checkPermission( at java.util.logging.LogManager.checkPermission( at java.util.logging.Logger.checkPermission( at java.util.logging.Logger.setLevel( at java.util.logging.LogManager.resetLogger( at java.util.logging.LogManager.reset( at java.util.logging.LogManager$ —-

    It’s time for some real software engineering (also known as Google Search). The LogManager’s–[Javadoc^] tells about the LoggingPermission that needs to be added to the existing list of permissions:


    grant codeBase “file:target/spring-petclinic-1.4.2.jar” { permission java.lang.RuntimePermission “getProtectionDomain”; … permission java.util.PropertyPermission “PID”, “read,write”; permission java.util.logging.LoggingPermission “control”; }; —-

    That makes it possible to go further.

    === Securing the reading of system properties and environment variables

    It’s even possible to watch Spring Boot log… until one realizes it’s made entirely of error messages about not being able to read a bunchload of system properties and environment variables. Here’s an excerpt:

    2017-01-22 00:30:17.118 INFO 46549 — [ main] o.s.w.c.s.StandardServletEnvironment : Caught AccessControlException when accessing system environment variable [logging.register_shutdown_hook]; its value will be returned [null]. Reason: access denied (“java.lang.RuntimePermission” “getenv.logging.register_shutdown_hook”) 2017-01-22 00:30:17.118 INFO 46549 — [ main] o.s.w.c.s.StandardServletEnvironment : Caught AccessControlException when accessing system property [logging_register-shutdown-hook]; its value will be returned [null]. Reason: access denied (“java.util.PropertyPermission” “logging_register-shutdown-hook” “read”) —-

    I will spare you dear readers a lot of trouble: there’s no sense in configuring every property one by one as JCache requires read and write permissions on all properties. So just remove every fine-grained PropertyPermission so far and replace it with a catch-all coarse-grained one:


    permission java.util.PropertyPermission “*”, “read,write”; —-


    Seems like security was not one of JCache developers first priority. The following snippet is the[code excerpt] for javax.cache.Caching.CachingProviderRegistry.getCachingProviders():


    if (System.getProperties().containsKey(JAVAX_CACHE_CACHING_PROVIDER)) { String className = System.getProperty(JAVAX_CACHE_CACHING_PROVIDER); … } —-

    Wow, it reads all properties! Plus the next line makes it a little redundant, no?

    As for environment variables, the Spring team seem to try to avoid developers configuration issues related to case and check every possible case combination, so there is a lot of different options.

    === Variables and subdirectories

    At one point, Spring’s embedded Tomcat attempts - and fails, to create a subfolder into the folder.

    java.lang.SecurityException: Unable to create temporary file at ~[na:1.8.0_92] at ~[na:1.8.0_92] at org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory.createTempDir(…) at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(…) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(…) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(…) … 16 common frames omitted —-

    One could get away with that by “hard-configuring” the path, but that would just be a major portability issue. Permissions are able to use System properties.

    The second issue is the subfolder: there’s no way of knowing the folder name, hence it’s not possible to configure it beforehand. However, file permissions accept any direct children or any descendant in the hierarachy; the former is set with jokers, and the second with dashes. The final configuration looks like this:


    permission “${}/-“, “read,write,delete”; —-

    === CGLIB issues

    CGLIB is used heavily in the Spring framework to extend classes at compile-time. By default, the name of a generated class:

    [quote] […] is composed of a prefix based on the name of the superclass, a fixed string incorporating the CGLIB class responsible for generation, and a hashcode derived from the parameters used to create the object.

    Consequently, one if faced with the following exception: access denied (""
      at ~[na:1.8.0_92]
      at [na:1.8.0_92]
      at java.lang.SecurityManager.checkPermission( ~[na:1.8.0_92]
      at java.lang.SecurityManager.checkRead( ~[na:1.8.0_92]
      at ~[na:1.8.0_92]
      at org.apache.catalina.webresources.DirResourceSet.getResource(...)
      at org.apache.catalina.webresources.StandardRoot.getResourceInternal(...)
      at org.apache.catalina.webresources.Cache.getResource( ~[tomcat-embed-core-8.5.6.jar!/:8.5.6]
      at org.apache.catalina.webresources.StandardRoot.getResource(...)
      at org.apache.catalina.webresources.StandardRoot.getClassLoaderResource(...)
      at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(...)
      at org.apache.catalina.loader.WebappClassLoaderBase$
      at org.apache.catalina.loader.WebappClassLoaderBase$
      at Method) [na:1.8.0_92]
      at org.apache.catalina.loader.WebappClassLoaderBase.findClass()
      at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader.findClassIgnoringNotFound()
      at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass()
      at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(...)
      at java.lang.Class.forName0(Native Method) [na:1.8.0_92]
      at java.lang.Class.forName( [na:1.8.0_92]

    It looks quite an easy file permission fix, but it isn’t: for whatever reason, the hashcode used by CGLIB to extend MultipartAutoConfiguration changes at every compilation. Hence, a more lenient generic permission is required:

    permission "src/main/webapp/WEB-INF/classes/org/springframework/boot/autoconfigure/web/*", "read";

    === Launching is not the end

    Unfortunately, once the application has been successfully launched doesn’t mean it stops there. Browsing the home page yields a new bunch of security exceptions.

    For example, Tomcat needs to bind to port 8080, but this is a potential insecure action: access denied ("" "localhost:8080" "listen,resolve")

    The permission to fix it is pretty straightforward:

    permission "localhost:8080", "listen,resolve";

    However, actually browsing the app brings a new exception: access denied ("" "[0:0:0:0:0:0:0:1]:56733" "accept,resolve")

    That wouldn’t be bad if the port number didn’t change with every launch. A few attempts reveal that it seems to start from around 55400. Good thing that the socket permission allows for a port range:

    permission "[0:0:0:0:0:0:0:1]:55400-", "accept,resolve";

    == Lessons learned

    Though it was very fulfilling to have created the policy file, the true value lies in the lessons learned.

    • The crafting of a custom policy file for a specific application is quite trivial, but very time-consuming. I didn’t finish completely and spent around one day for a small-sized application. Time might be a valid reason why policy files are never in use.
    • For large applications, I believe it’s not only possible but desirable to automate the crafting process: run the app, read the exception, create the associated permission, and update the policy file accordingly.
    • Patterns are recognizable in the policy file: sets of permissions are dedicated to a specific library, such as Spring Boot’s actuator. If each framework/library would provide the minimum associated policy file that allows it to work correctly, crafting a policy file for an app would just mean aggregating all files for every library.
    • Randomness (such as random port number) and bad coding practices (such as JCache’s) require more coarse-grained permissions. On one hand, it speeds up the crafting process; on the other hand, it increases the potential attack surface.

    In all cases, running the JVM in sandbox mode is not an option in security-aware environments.

    To go further:

    •[Policy file syntax^]
    •[Permissions in the JDK^]
    •[Security documentation^]
    •[End result policy file] (nearly finished)
    Categories: Java Tags: JVMsecuritySpring Bootpolicy
  • The Java Security Manager: why and how?

    Generally, security concerns are boring for developers. I hope this article is entertaining enough for you to read it until the end since it tackles a very serious issue on the JVM.


    Last year, at Joker conference, my colleague Volker Simonis showed a snippet that looked like the following:

    public class StrangeReflectionExample {
        public Character aCharacter;
        public static void main(String... args) throws Exception {
            StrangeReflectionExample instance = new StrangeReflectionExample();
            Field field = StrangeReflectionExample.class.getField("aCharacter");
            Field type = Field.class.getDeclaredField("type");
            type.set(field, String.class);
            field.set(instance, 'A');

    Now a couple of questions:

    1. Does this code compile?
    2. If yes, does it run?
    3. If yes, what does it display?

    Answers below (dots to let you think before checking them).

















    This code compiles just fine. In fact, it uses the so-called reflection API (located in the java.lang.reflect package) which is fully part of the JDK.

    Executing this code leads to the following exception:

    Exception in thread "main" java.lang.IllegalArgumentException:
            Can not set java.lang.String field
                to java.lang.Character
    	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(
    	at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(
    	at sun.reflect.UnsafeObjectFieldAccessorImpl.set(
    	at java.lang.reflect.Field.set(
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(
    	at java.lang.reflect.Method.invoke(
    	at com.intellij.rt.execution.application.AppMain.main(

    So, despite the fact that we defined the type of the aCharacter attribute as a Character at development time, the reflection API is able to change its type to String at runtime! Hence, trying to set it to 'A' fails.

    Avoiding nasty surprises with the Security Manager

    Reflection is not the only risky operation one might want to keep in check on the JVM. Reading a file or writing one also belong to the set of potentially dangerous operations. Fortunately, the JVM has a system to restrict those operations. Unfortunately, it’s not set by default.

    In order to activate the SecurityManager, just launch the JVM with the system property i.e. java At this point, the JVM will use the default JRE policy. It’s configured in the file located at %JAVA_HOME%/lib/security/java.policy (for Java 8). Here’s a sample of this file:

    grant codeBase "file:${{java.ext.dirs}}/*" {
    grant {
            permission java.lang.RuntimePermission "stopThread";
            permission "localhost:0", "listen";
            permission java.util.PropertyPermission "java.version", "read";
            permission java.util.PropertyPermission "java.vendor", "read";

    The first section - grant codeBase, is about which code can be executed; the second - grant, is about specific permissions.

    Regarding the initial problem regarding reflection mentioned above, the second part is the most relevant. One can read the source of the AccessibleObject.setAccessible() method:

    SecurityManager sm = System.getSecurityManager();
    if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
    setAccessible0(this, flag);

    Every sensitive method to a Java API has the same check through the Security Manager. You can verify that for yourself in the following code:

    • Thread.stop()
    • Socket.bind()
    • System.getProperty()
    • etc.

    Using an alternate java.policy file

    Using the JRE’s policy file is not convenient when one uses the same JRE for different applications. Given the current micro-service trend, this might not be the case. However, with automated provisioning, it might be more convenient to always provision the same JRE over and over and let each application provides its own specific policy file.

    To add another policy file in addition to the default JRE’s, thus adding more permissions, launch the JVM with:


    To replace the default policy file with your own, launch the JVM with:


    Note the double equal sign.

    Configuring your own policy file

    Security configuration can be either based on a:

    Black list
    In a black list scenario, everything is allowed but exceptions can be configured to disallow some operations.
    White list
    On the opposite, in a white list scenario, only operations that are explicitly configured are allowed. By default, all operations are disallowed.

    If you want to create your own policy file, it’s suggested you start with a blank one and then launch your app. As soon, as you get a security exception, add the necessary permission is the policy. Repeat until you have all necessary permissions. Following this process will let you have only the minimal set of permissions to run the application, thus implementing the least privilege security principle.

    Note that if you’re using a container or a server, you’ll probably require a lot of those permissions, but this is the price to pay to secure your JVM against abuses.


    I never checked policy files in production, but since I never had any complain, I assume the JVM’s policy was never secured. This is a very serious problem! I hope this article will raise awareness regarding that lack of hardening - especially since with the latest JVM, you can create and compile Java code on the fly, leading to even more threats.

    To go further:

    Categories: Java Tags: JVMsecurity
  • Do we need other languages on the JVM?

    It seems a trend has caught on and accelerated recently: every organization worth his salt in the Java ecosystem feels the need to create its own language that runs on the Java Virtual Machine. Side by side with legacy languages like Jython and JRuby, and along more promoted ones like Scala, Red Hat announced Ceylon and now it’s JetBrain’s turn with Kotlin.

    Why so many languages?

    However, the real question is not whether we need them (the answer is a simple ‘no’ since we created software without them), but why there is a sudden rise.

    The developer perspective

    Truth to be told, Java is an old-timer in today’s changing world. I began Java 10 years ago and I was not a pioneer at the time. Java the language’s evolutions has been hindered by:

    • a lack of competitors prior to .Net
    • a requirement of compatibility with older versions
    • a change process that encompassed companies with divergent interests

    The mixing of the three makes any update on the language a real challenge. The last major change dates back to Java 5, which is End Of Life…

    So, instead of following the slow Java path, some developers prefer to use the highway to features not present in the language, such as Scala’s functional programming.

    The new leader of the pack

    Although I have a clear view why developers may want to use languages other than Java on the JVM, I can only speculate as why companies are releasing them. IMHO, big players in the Java ecosystem are afraid of Oracle’s control over Java and are trying to escape potential future costs of using Java. It’s a real risk considering Oracle’s stance on TCK as well as the Hologic fiasco.

    Risks posed by other languages

    Although the previous reasons are in favour of language diversification, there also are some strong arguments agains their uses.

    Skills management

    The Java ecosystem is very rich, and one doesn’t just qualify as a Java developer, but as a Java/Spring/Hibernate developer for example. In the event of a coming of other languages, recruitment will be even harder. And from a developer perspective, skills needed will be more widespread, thus leading to a decrease of knowledge in each individual language (no, you cannot be a master of many languages).

    Loss of weight

    Today, the market can roughly be divided into Java, .Net and PHP. I agree that others exist but frankly, they do not count as major players (Flex excepted but it’s staying on the GUI). If the Java language gives way to a bunch of other languages, however fantastic they are, the Java community as a whole will be fragmented into many tiny communities that won’t play nicely with one another. Notice that it’s beginning to happen if you read the comments on Ceylon, some definitely look like a war waiting to happen.

    Other cases

    In the previous sections, I deliberately left out some cases that are sensitive. I don’t want to start a flame war but since I tend to disagree with some of them, here are my counter-arguments.


    Some complain about Java verbosity and choose a language that will make them write (and read) less code. Although I agree that it’s more maintainable to write 10 LOC against 100, I don’t see a problem in writing 15. I respectfully remind everyone that not every developer is top-notch and that writing explicit code (and reading it) goes a long way toward having maintainable software.

    For those obsessed with LOC-optimization, I gladly provide this contest.

    Operator overloading

    Java doesn’t have operator overloading. Again, this is not a problem, at least for me: this means I can count that 1+1 does what I expect, and not another circonvoluted operation. As a counter-example, just have a look at Scala Akka’s bang operator (for newbies, there are also bang bang and bang bang bang). Sure it’s short but you really need to know what it does. If it’s the only library you use, that’s fine; if not, you’re headed for a world of doubts.

    Technical vs business

    Only the future will tell but I’m afraid the trend is that languages going to go beyond a nice are ones that free developers from purely technical tasks with no business value, such as memory management, portability, persistance, and so on. Do the former two ring any bell? Java surfed on them. Powerful or hype are adjectives that managers don’t care about. Since they are in position to decide, I think that because a language can do more than another has no interest other than a educational one.


    For now, my point of view is that negative points against all these new languages are not counter-balanced by positive ones. Of course, I’m a pragmatic by heart so I’m all ears if I’ve missed a point. In the end, though, only time will tell.

    Categories: Java Tags: JVMlanguage