making JetBrains IDEs run faster…

disclaimer / warning

This post contains advice / instructions on how to change your JetBrains installation. Following them may break your installation, and I do not take any responsibility for your actions in doing so 🙂

directions

Install a version 15 JDK such as the Azul Zulu JVM by following the instructions at https://www.azul.com/downloads/?package=jdk Other JVM implementations are available.

IDEA and CLion won’t start with JDK 16 or later, so I’m using JDK 15 for those. All the other JetBrains IDEs work with JDK 16. In all cases, features using the JCEF [1] runtime library, which is bundled with the JBR [2], will not be available.

I’m using these options on Debian/unstable on all JetBrains IDEs, with both JDK 15 and JDK 16.

  -XX:+IgnoreUnrecognizedVMOptions
  -XX:+UnlockExperimentalVMOptions
  -XX:+UseZGC
  -XX:-UseG1GC
  -XX:C1CompileThreshold=100
  -XX:C2CompileThreshold=5000
  -Xms4G
  -Xmx4G
  -XX:ReservedCodeCacheSize=512m
  -XX:SoftRefLRUPolicyMSPerMB=50
  -XX:CICompilerCount=2
  --illegal-access=permit

Adding -XX:ReservedCodeCacheSize= and -XX:SoftRefLRUPolicyMSPerMB= made all the difference in keeping heap usage down. I have not yet experimented with different values for those parameters.

The option –illegal-access=permit is required on JDK 16, but this option was removed in JDK 17, and because of this (but probably not only this) I haven’t yet been able to make any JetBrains IDE work with JDK 17.

In adjusting all of these settings, YMMV depending on your system. Good luck!

[1] https://github.com/JetBrains/jcef
[2] which is currently based on JDK 11

jaotc

Since day one, startup time has been a painful part of Java. Nowadays we are blessed with modules in the JDK and we can compile them ahead of time and load them into the JDK at runtime. Seems like it might a good idea for big applications, but actually the benefits are greater for smaller programs.

This script invokes the jaotc binary to create a single shared object library file from the modules in the JDK. Note that the ZGC garbage collector is not compatible with the use of jaotc.

#! /bin/bash

set -o nounset

# java ------------------------------------------------------------------------

java_home=${JAVA_HOME:-/usr/lib/jvm/zulu16}
echo "java_home is [${java_home}]"

java_flags=( -XX:+UseG1GC -XX:-UseZGC )
java_name=$(basename ${java_home})
aot_so=${HOME}/lib/java/native/$(uname -m)-linux/aot.${java_name}.so
echo "output shared object file is [${aot_so}]"


# enumerate modules -----------------------------------------------------------

modules=()

jmod_files=( ${java_home}/jmods/*.jmod )
for _jmod in ${jmod_files[@]}; do
    module=$(basename ${_jmod/.jmod/})
    case ${module} in
        jdk.hotspot.agent) ;;
        jdk.incubator) ;;
        jdk.incubator.*) ;;
        jdk.internal.vm.compiler) ;;
        jdk.jcmd) ;;
        *) modules+=( ${module} ) ;;
    esac
done


# construct command line ------------------------------------------------------

argv=()
argv+=( ${java_home}/bin/jaotc )
for flag in ${java_flags[@]}; do
    argv+=( -J$flag )
done
argv+=( --compile-for-tiered )
argv+=( --output ${aot_so} )
argv+=( --module ${modules[@]} )


# execute --------------------------------------------------------------------

mkdir -p $(dirname ${aot_so})
${argv[@]}

This step above will take a few minutes or a bit longer, depending on your system.

Add these lines to your IntelliJ custom VM options:

-XX:AOTLibrary=/home/username/lib/java/native/x86_64-linux/aot.zulu16.so
-Xshare:on

(Note the /home/username and change it to your home directory.) Restart the IDE — and you should see it start much faster.

Leave a Reply

Your email address will not be published. Required fields are marked *