RFR: 8336856: Optimize String Concat [v39]

Shaojin Wen duke at openjdk.org
Fri Aug 9 02:47:37 UTC 2024


On Thu, 8 Aug 2024 11:43:07 GMT, Shaojin Wen <duke at openjdk.org> wrote:

>> This PR implements the same algorithm as the current generateMHInlineCopy based on bytecode to improve startup performance.
>
> Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   fix comments

I have reviewed the code several times and fixed anything I thought could be improved. 

I didn't find a way to test class unloading. For example, I dynamically loaded a method with string concatenation from byte[] code, and then allocated a very large array to trigger OutOfMemoryError, but the class of InlineHiddenClassStrategy.CACHE was still not removed.

Below is my test code:

* Concat Class
Compile the following code into a class and rename it to .clazz as a resource file


public class Concat {
    public static String concat(String a, String b, int i, long j) {
        return a + b + i + j;
    }
}


* TestClass

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;

public class ClassLoadingTest {
    public static void main(String[] args) throws Throwable {
        for (int i = 0; i < 10_000_000; i++) {
            perf(i);
        }
    }

    public static void perf(int i) throws Throwable {
        URL resource = ClassLoadingTest.class.getClassLoader().getResource("Concat.clazz");
        byte[] code = FileUtils.readFileToByteArray(new File(resource.getFile()));

        MyClassLoader classLoader = new MyClassLoader();
        Class<?> concatClass = classLoader.defineClass("Concat", code);
        Method concat = concatClass.getMethod("concat", String.class, String.class, int.class, long.class);
        Object result = concat.invoke(null, "abc", "d", i, 0L);
        gc();
        if (i % 1000 == 0) {
            System.out.println(result);
        }
    }

    public static void gc() {
        try {
            long[] array = new long[Integer.MAX_VALUE];
            System.out.println(array.length);
            System.gc();
        } catch (OutOfMemoryError ignored) {
            // skip
        }
    }

    static class MyClassLoader extends ClassLoader {
        public Class<?> defineClass(String name, byte[] b) {
            return defineClass(name, b, 0, b.length);
        }
    }
}


* Script to check for class unloading

jps | grep ClassLoadingTest

jmap -histo <pid> | grep StringConcat

-------------

PR Comment: https://git.openjdk.org/jdk/pull/20273#issuecomment-2277042311


More information about the core-libs-dev mailing list