import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;

public class ManyFieldsRegression {
    // There are about 3 items for each field in the constant pool
    private static final int METHODS = 100;
    private static final int FIELDS = 210;

    public static void main(String[] args) throws IOException, InterruptedException {
        File cFile = File.createTempFile("CCC", ".java");
        try (var writer = new PrintWriter(cFile)) {
            writer.println("class CCC {");
            for (int i = 0; i < METHODS * FIELDS; ++i) {
                writer.printf("static int f%d;%n", i);
            }
            writer.println("public static void main(String[] args) {");
            for (int i = 0; i < METHODS; ++i) {
                writer.printf("sub%d();%n", i);
            }
            writer.println("}");
            for (int i = 0; i < METHODS; ++i) {
                writer.printf("static void sub%d() {%n", i);
                for (int j = 0; j < FIELDS; ++j) {
                    if (i == 0 && j == 0) {
                        writer.println("f0 = 1;");
                    } else {
                        writer.printf("f%d = f%d;%n", i * FIELDS + j, i * FIELDS + j - 1);
                    }
                }
                writer.println("}");
            }
            writer.println("}");
        }
        System.err.println("Written " + cFile);
        String javaHome = System.getProperty("java.home");
        int javacExitValue = new ProcessBuilder().inheritIO().command(javaHome + "/bin/javac", "-d", cFile.getParent(), cFile.getPath()).start().waitFor();
        if (javacExitValue != 0) throw new IOException("Compilation failed");
        long startTime = System.nanoTime();
        new ProcessBuilder().inheritIO().command(javaHome + "/bin/java", "-cp", cFile.getParent(), "CCC").start().waitFor();
        long endTime = System.nanoTime();
        System.err.printf("Execution took %d ms%n", TimeUnit.NANOSECONDS.toMillis(endTime - startTime));
        // cleanup
//        Path.of(cFile.getParent(), "CCC.class").toFile().delete();
//        cFile.delete();
    }
}
