Why/When you would not want to have Java 8 UseStringDeduplication enabled in JVM?

I absolutely understand that this does not answer the question, just wanted to mention that jdk-9 introduces one more optimization that is on by default called :

-XX:+CompactStrings

where Latin1 characters occupy a single byte instead of two (via a char). Because of that change many internal methods of String have changed - they act the same to the user, but internally they are faster in a lot of cases.

Also in case of Strings for concatenating two Strings together via the plus sign the javac is going to generate different bytecode.

There is no bytecode instruction that concatenates two Strings together so the javac would generate a

StringBuilder#append

in the back-end. Until jdk-9.

Now the bytecode delegates to

StringConcatFactory#makeConcatWithConstants

or

StringConcatFactory#makeConcat

via the invokedynamic bytecode instruction:

   aload_0
   1: aload_2
   2: aload_1
   3: invokedynamic #8,  0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
   8: areturn 

How the two strings are concatenated is a Runtime decision now. it could be still a StringBuilder or it could be a concatenation of byte arrays, etc. All you know that this can change and you will get the fastest possible solution.

EDIT

I've just debugged and saw that there are quite a lot of strategies on how to append these Strings:

    private enum Strategy {
    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder}.
     */
    BC_SB,

    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder};
     * but trying to estimate the required storage.
     */
    BC_SB_SIZED,

    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder};
     * but computing the required storage exactly.
     */
    BC_SB_SIZED_EXACT,

    /**
     * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
     * This strategy also tries to estimate the required storage.
     */
    MH_SB_SIZED,

    /**
     * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
     * This strategy also estimate the required storage exactly.
     */
    MH_SB_SIZED_EXACT,

    /**
     * MethodHandle-based generator, that constructs its own byte[] array from
     * the arguments. It computes the required storage exactly.
     */
    MH_INLINE_SIZED_EXACT
}

The default being:

MH_INLINE_SIZED_EXACT


Cases where String de-duplication could be harmful include:

  • There are lots of strings but a very low probability of duplicates: the time overhead of looking for duplicates and the space overhead of the de-duping data structure would not be repaid.
  • There is a reasonable probability of duplicates, but most strings die in within a couple of GC cycles1 anyway. The de-duplication is less beneficial if the de-duped strings were going to be GC'ed soon anyway.

    (This is not about strings that don't survive the first GC cycle. It would make no sense for the GC to even try to de-dup strings that it knows to be garbage.)

We can only speculate as to why the Java team didn't turn on de-duping by default, but they are in a much better position to make rational (i.e. evidence based) decisions on this that you and I. My understanding is that they have access to many large real-world applications for benchmarking / trying out the effects of optimizations. They may also have contacts in partner or customer organizations with similarly large code-bases and concerns about efficiency ... who they can ask for feedback on whether optimizations in an early access release work as expected.

1 - This depends on the value of the StringDeduplicationAgeThreshold JVM setting. This defaults to 3 meaning that (roughly) a string has to survive 3 minor collections or a major collection to be considered for de-duping. But anyhow, if a string is de-duped and then found to be unreachable shortly afterwards, the de-duping overheads will not be repaid for that string.


If you are asking when you should consider enabling de-duping, my advice would be to try it and see if it helps on a per-application basis. But you need to do some application-level benchmarking (which takes effort!) to be sure that the de-duping is beneficial ...

A careful read of JEP 192 would also help you understand the issues, and make a judgment on how they might apply for your Java application.