content: package com.alibaba.fastjson2.benchmark;
  
  import org.openjdk.jmh.annotations.Benchmark;
  import org.openjdk.jmh.annotations.Mode;
  import org.openjdk.jmh.runner.Runner;
  import org.openjdk.jmh.runner.RunnerException;
  import org.openjdk.jmh.runner.options.Options;
  import org.openjdk.jmh.runner.options.OptionsBuilder;
  
  import java.lang.invoke.*;
  import java.lang.reflect.Field;
  import java.util.concurrent.TimeUnit;
  import java.util.function.BiFunction;
  
  import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
  
  public class StringCreateBenchmark {
      static final BiFunction<char[], Boolean, String> STRING_CREATOR = getStringCreator();
      static final char[] chars = new char[128];
      static long valueOffset;
  
      static {
          try {
              Field field = String.class.getDeclaredField("value");
              field.setAccessible(true);
              valueOffset = UNSAFE.objectFieldOffset(field);
          } catch (NoSuchFieldException e) {
              e.printStackTrace();
          }
      }
  
      public static BiFunction<char[], Boolean, String> getStringCreator() {
          try {
              MethodHandles.Lookup caller = MethodHandles.lookup().in(String.class);
              Field modes = MethodHandles.Lookup.class.getDeclaredField("allowedModes");
              modes.setAccessible(true);
              modes.setInt(caller, -1);   // -1 == Lookup.TRUSTED
              // create handle for shared String constructor
              MethodHandle handle = caller.findConstructor(
                      String.class,
                      MethodType.methodType(void.class, char[].class, boolean.class)
              );
  
              CallSite callSite = LambdaMetafactory.metafactory(
                      caller,
                      "apply",
                      MethodType.methodType(BiFunction.class),
                      handle.type().generic(),
                      handle,
                      handle.type()
              );
              return (BiFunction) callSite.getTarget().invokeExact();
          } catch (Throwable e) {
              throw new RuntimeException(e);
          }
      }
  
      @Benchmark
      public String creator() {
          return STRING_CREATOR.apply(chars, Boolean.TRUE);
      }
  
      @Benchmark
      public String newString() {
          return new String(chars);
      }
  
      @Benchmark
      public String unsafe() throws Exception {
          String str = (String) UNSAFE.allocateInstance(String.class);
          UNSAFE.putObject(str, valueOffset, chars);
          return str;
      }
  
      public void creator_benchmark() {
          long start = System.currentTimeMillis();
          for (int i = 0; i < 1000_000_000; i++) {
              creator();
          }
          long millis = System.currentTimeMillis() - start;
          System.out.println("creator : " + millis);
      }
  
      public void new_benchmark() throws Exception {
          long start = System.currentTimeMillis();
          for (int i = 0; i < 1000_000; i++) {
              unsafe();
          }
          long millis = System.currentTimeMillis() - start;
          System.out.println("new : " + millis);
      }
  
      //    @Test
      public void test_benchmark() throws Exception {
          for (int i = 0; i < 10; i++) {
              new_benchmark();
          }
      }
  
      public static void main(String[] args) throws RunnerException {
          Options options = new OptionsBuilder()
                  .include(StringCreateBenchmark.class.getName())
                  .mode(Mode.Throughput)
                  .timeUnit(TimeUnit.MILLISECONDS)
                  .forks(1)
                  .build();
          new Runner(options).run();
      }
  }
  