You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/12/06 21:37:26 UTC

[groovy] 01/01: GROOVY-10278, GROOVY-10281: refactor `CompilerConfiguration` somewhat

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-10278
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit e7f540335f356bc9c301f6dac63084dc22a472bd
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Dec 6 15:36:54 2021 -0600

    GROOVY-10278, GROOVY-10281: refactor `CompilerConfiguration` somewhat
---
 .../groovy/ast/decompiled/AsmDecompiler.java       |   2 +-
 .../ast/decompiled/FormalParameterParser.java      |   2 +-
 .../groovy/ast/decompiled/TypeSignatureParser.java |   2 +-
 .../groovy/classgen/AsmClassGenerator.java         |  21 +-
 .../codehaus/groovy/classgen/ExtendedVerifier.java |   5 +-
 .../groovy/classgen/asm/WriterController.java      |  10 +-
 .../classgen/asm/util/LoggableClassVisitor.java    |  38 --
 .../classgen/asm/util/LoggableTextifier.java       | 538 ---------------------
 .../groovy/control/CompilerConfiguration.java      | 516 ++++++++------------
 .../groovy/runtime/ProxyGeneratorAdapter.java      |   2 +-
 .../runtime/callsite/GroovySunClassLoader.java     |   2 +-
 .../transform/RecordTypeASTTransformation.java     |   3 +-
 .../groovy/transform/SealedASTTransformation.java  |   3 +-
 src/test/gls/annotations/AnnotationsTestBase.java  |   2 +-
 src/test/gls/generics/GenericsTestBase.java        |   2 +-
 src/test/groovy/bugs/Groovy10281.groovy            |  70 ---
 .../classgen/asm/AbstractBytecodeTestCase.groovy   |   4 +-
 .../groovy/control/CompilerConfigurationTest.java  |  29 +-
 .../main/java/org/codehaus/groovy/ant/Groovyc.java |  15 +-
 19 files changed, 263 insertions(+), 1003 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java b/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java
index 3a66c08..986d5d5 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java
@@ -42,7 +42,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 import static org.codehaus.groovy.control.ResolveVisitor.EMPTY_STRING_ARRAY;
 
 /**
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java
index 2e7b1eb..6f2c919 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/FormalParameterParser.java
@@ -26,7 +26,7 @@ import org.objectweb.asm.signature.SignatureVisitor;
 import java.util.ArrayList;
 import java.util.List;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 
 abstract class FormalParameterParser extends SignatureVisitor {
     private final AsmReferenceResolver resolver;
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java
index 2a7b1a5..dc854e2 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/TypeSignatureParser.java
@@ -28,7 +28,7 @@ import org.objectweb.asm.signature.SignatureVisitor;
 import java.util.ArrayList;
 import java.util.List;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 
 abstract class TypeSignatureParser extends SignatureVisitor {
 
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 32c9ce5..6a3ac1a 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -170,6 +170,7 @@ import static org.objectweb.asm.Opcodes.ACONST_NULL;
 import static org.objectweb.asm.Opcodes.ALOAD;
 import static org.objectweb.asm.Opcodes.ANEWARRAY;
 import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASM9;
 import static org.objectweb.asm.Opcodes.ASTORE;
 import static org.objectweb.asm.Opcodes.ATHROW;
 import static org.objectweb.asm.Opcodes.BASTORE;
@@ -255,21 +256,31 @@ public class AsmClassGenerator extends ClassGenerator {
     private static final MethodCaller createPojoWrapperMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createPojoWrapper");
     private static final MethodCaller createGroovyObjectWrapperMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createGroovyObjectWrapper");
 
-    private final Map<String,ClassNode> referencedClasses = new HashMap<>();
-    private boolean passingParams;
+    /**
+     * The ASM API version used when loading/parsing classes and generating proxy adapter classes.
+     */
+    public static final int ASM_API_VERSION = ASM9;
+
+    /**
+     * Add marker in the bytecode to show source-bytecode relationship?
+     */
+    public static final boolean ASM_DEBUG = false;
 
     public static final boolean CREATE_DEBUG_INFO = true;
     public static final boolean CREATE_LINE_NUMBER_INFO = true;
-    public static final boolean ASM_DEBUG = false; // add marker in the bytecode to show source-bytecode relationship
     public static final String MINIMUM_BYTECODE_VERSION = "_MINIMUM_BYTECODE_VERSION";
 
-    private WriterController controller;
-    private ASTNode currentASTNode;
+    //--------------------------------------------------------------------------
+
+    private final Map<String,ClassNode> referencedClasses = new HashMap<>();
+    private boolean passingParams;
 
     private final SourceUnit source;
     private final GeneratorContext context;
+    private WriterController controller;
     private ClassVisitor classVisitor;
     private final String sourceFile;
+    private ASTNode currentASTNode;
 
     public AsmClassGenerator(final SourceUnit source, final GeneratorContext context, final ClassVisitor classVisitor, final String sourceFile) {
         this.source = source;
diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index a83e6b8..3cebfb3 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -40,7 +40,6 @@ import org.codehaus.groovy.ast.stmt.ReturnStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.ast.tools.ParameterUtils;
 import org.codehaus.groovy.control.AnnotationConstantsVisitor;
-import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.control.ErrorCollector;
 import org.codehaus.groovy.control.SourceUnit;
 import org.objectweb.asm.Opcodes;
@@ -475,6 +474,8 @@ public class ExtendedVerifier extends ClassCodeVisitorSupport {
      */
     @Deprecated
     protected boolean isAnnotationCompatible() {
-        return CompilerConfiguration.isPostJDK5(this.source.getConfiguration().getTargetBytecode());
+        return org.codehaus.groovy.runtime.StringGroovyMethods.isAtLeast(
+                    getSourceUnit().getConfiguration().getTargetBytecode(),
+                    org.codehaus.groovy.control.CompilerConfiguration.JDK5);
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index 0f56c04..b15d83e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -28,7 +28,6 @@ import org.codehaus.groovy.classgen.GeneratorContext;
 import org.codehaus.groovy.classgen.asm.indy.IndyBinHelper;
 import org.codehaus.groovy.classgen.asm.indy.IndyCallSiteWriter;
 import org.codehaus.groovy.classgen.asm.indy.InvokeDynamicWriter;
-import org.codehaus.groovy.classgen.asm.util.LoggableClassVisitor;
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.control.SourceUnit;
 import org.objectweb.asm.ClassVisitor;
@@ -133,11 +132,10 @@ public class WriterController {
         this.typeChooser = new StatementMetaTypeChooser();
     }
 
-    private static ClassVisitor createClassVisitor(final ClassVisitor cv, final CompilerConfiguration config) {
-        if (!config.isLogClassgen() || cv instanceof LoggableClassVisitor) {
-            return cv;
-        }
-        return new LoggableClassVisitor(cv, config);
+    private static ClassVisitor createClassVisitor(final ClassVisitor visitor, final CompilerConfiguration config) {
+        return visitor;
+//        if (visitor instanceof org.objectweb.asm.util.TraceClassVisitor || !SystemUtil.getBooleanSafe("groovy.log.classgen")) return visitor;
+//        return new org.objectweb.asm.util.TraceClassVisitor(visitor, Optional.ofNullable(config.getOutput()).orElseGet(() -> new PrintWriter(System.out, true)));
     }
 
     //--------------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/util/LoggableClassVisitor.java b/src/main/java/org/codehaus/groovy/classgen/asm/util/LoggableClassVisitor.java
deleted file mode 100644
index 5fd97a9..0000000
--- a/src/main/java/org/codehaus/groovy/classgen/asm/util/LoggableClassVisitor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.codehaus.groovy.classgen.asm.util;
-
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.util.TraceClassVisitor;
-
-/**
- * A ClassVisitor proxy, which can log bytecode generation
- *
- * @since 2.5.0
- */
-public class LoggableClassVisitor extends ClassVisitor {
-    public LoggableClassVisitor(final ClassVisitor cv) {
-        this(cv, CompilerConfiguration.DEFAULT);
-    }
-
-    public LoggableClassVisitor(ClassVisitor cv, CompilerConfiguration compilerConfiguration) {
-        super(CompilerConfiguration.ASM_API_VERSION, new TraceClassVisitor(cv, new LoggableTextifier(compilerConfiguration), null));
-    }
-}
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/util/LoggableTextifier.java b/src/main/java/org/codehaus/groovy/classgen/asm/util/LoggableTextifier.java
deleted file mode 100644
index 3d29b60..0000000
--- a/src/main/java/org/codehaus/groovy/classgen/asm/util/LoggableTextifier.java
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.codehaus.groovy.classgen.asm.util;
-
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.Handle;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.TypePath;
-import org.objectweb.asm.util.Printer;
-import org.objectweb.asm.util.Textifier;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-/**
- * Logging bytecode generation, which can make debugging easy
- *
- * @since 2.5.0
- */
-public class LoggableTextifier extends Textifier {
-
-    private final CompilerConfiguration compilerConfiguration;
-    private final PrintWriter out;
-    private int lineCount;
-
-    public LoggableTextifier() {
-        this(CompilerConfiguration.DEFAULT);
-    }
-
-    public LoggableTextifier(final CompilerConfiguration compilerConfiguration) {
-        super(CompilerConfiguration.ASM_API_VERSION);
-        this.compilerConfiguration = compilerConfiguration;
-        this.out = Optional.ofNullable(compilerConfiguration.getOutput()).orElseGet(() -> new PrintWriter(System.out, true));
-    }
-
-    @Override
-    protected Textifier createTextifier() {
-        return new LoggableTextifier(compilerConfiguration);
-    }
-
-    protected void log() {
-        int textSize = text.size();
-        List<Object> bcList = new ArrayList<>();
-        for (int i = lineCount; i < textSize; i += 1) {
-            Object bc = text.get(i);
-            if (!(bc instanceof List && ((List<?>) bc).isEmpty())) {
-                bcList.add(bc);
-            }
-        }
-        if (!bcList.isEmpty()) {
-            out.print(getInvocationPositionInfo());
-            for (Object bc : bcList) {
-                out.print(bc);
-            }
-        }
-        lineCount = textSize;
-    }
-
-    private String getInvocationPositionInfo() {
-        int maxDepth = compilerConfiguration.getLogClassgenStackTraceMaxDepth();
-        return maxDepth <= 0 ? "" : Arrays.stream(new Throwable().getStackTrace()).filter(stackTraceElement ->
-            stackTraceElement.getClassName().contains(".groovy.") && !stackTraceElement.getClassName().endsWith(".LoggableTextifier")
-        ).map(stackTraceElement ->
-            String.format("%30s// %s#%s:%s%n", "", stackTraceElement.getClassName(), stackTraceElement.getMethodName(), stackTraceElement.getLineNumber())
-        ).limit(maxDepth).collect(Collectors.joining());
-    }
-
-    //--------------------------------------------------------------------------
-
-    @Override
-    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-        super.visit(version, access, name, signature, superName, interfaces);
-        log();
-    }
-
-    @Override
-    public void visitSource(String file, String debug) {
-        super.visitSource(file, debug);
-        log();
-    }
-
-    @Override
-    public Printer visitModule(final String name, final int access, final String version) {
-        Printer p = super.visitModule(name, access, version);
-        log();
-        return p;
-    }
-
-    @Override
-    public void visitOuterClass(String owner, String name, String desc) {
-        super.visitOuterClass(owner, name, desc);
-        log();
-    }
-
-    @Override
-    public Textifier visitClassAnnotation(String desc, boolean visible) {
-        Textifier t = super.visitClassAnnotation(desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
-        Printer t = super.visitClassTypeAnnotation(typeRef, typePath, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitClassAttribute(Attribute attr) {
-        super.visitClassAttribute(attr);
-        log();
-    }
-
-    @Override
-    public void visitInnerClass(String name, String outerName, String innerName, int access) {
-        super.visitInnerClass(name, outerName, innerName, access);
-        log();
-    }
-
-    @Override
-    public Textifier visitField(int access, String name, String desc, String signature, Object value) {
-        Textifier t = super.visitField(access, name, desc, signature, value);
-        log();
-        return t;
-    }
-
-    @Override
-    public Textifier visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-        Textifier t = super.visitMethod(access, name, desc, signature, exceptions);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitClassEnd() {
-        super.visitClassEnd();
-        log();
-    }
-
-    @Override
-    public void visitRequire(String require, int access, String version) {
-        super.visitRequire(require, access, version);
-        log();
-    }
-
-    @Override
-    public void visitExport(String export, int access, String... modules) {
-        super.visitExport(export, access, modules);
-        log();
-    }
-
-    @Override
-    public void visitUse(String use) {
-        super.visitUse(use);
-        log();
-    }
-
-    @Override
-    public void visitProvide(String provide, String... providers) {
-        super.visitProvide(provide, providers);
-        log();
-    }
-
-    @Override
-    public void visitModuleEnd() {
-        super.visitModuleEnd();
-        log();
-    }
-
-    @Override
-    public void visit(String name, Object value) {
-        super.visit(name, value);
-        log();
-    }
-
-    @Override
-    public void visitEnum(String name, String desc, String value) {
-        super.visitEnum(name, desc, value);
-        log();
-    }
-
-    @Override
-    public Textifier visitAnnotation(String name, String desc) {
-        Textifier t = super.visitAnnotation(name, desc);
-        log();
-        return t;
-    }
-
-    @Override
-    public Textifier visitArray(String name) {
-        Textifier t = super.visitArray(name);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitAnnotationEnd() {
-        super.visitAnnotationEnd();
-        log();
-    }
-
-    @Override
-    public Textifier visitFieldAnnotation(String desc, boolean visible) {
-        Textifier t = super.visitFieldAnnotation(desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
-        Printer t = super.visitFieldTypeAnnotation(typeRef, typePath, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitFieldAttribute(Attribute attr) {
-        super.visitFieldAttribute(attr);
-        log();
-    }
-
-    @Override
-    public void visitFieldEnd() {
-        super.visitFieldEnd();
-        log();
-    }
-
-    @Override
-    public void visitParameter(String name, int access) {
-        super.visitParameter(name, access);
-        log();
-    }
-
-    @Override
-    public Textifier visitAnnotationDefault() {
-        Textifier t = super.visitAnnotationDefault();
-        log();
-        return t;
-    }
-
-    @Override
-    public Textifier visitMethodAnnotation(String desc, boolean visible) {
-        Textifier t = super.visitMethodAnnotation(desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
-        Printer t = super.visitMethodTypeAnnotation(typeRef, typePath, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Textifier visitParameterAnnotation(int parameter, String desc, boolean visible) {
-        Textifier t = super.visitParameterAnnotation(parameter, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitMethodAttribute(Attribute attr) {
-        super.visitMethodAttribute(attr);
-        log();
-    }
-
-    @Override
-    public void visitCode() {
-        super.visitCode();
-        log();
-    }
-
-    @Override
-    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
-        super.visitFrame(type, nLocal, local, nStack, stack);
-        log();
-    }
-
-    @Override
-    public void visitInsn(int opcode) {
-        super.visitInsn(opcode);
-        log();
-    }
-
-    @Override
-    public void visitIntInsn(int opcode, int operand) {
-        super.visitIntInsn(opcode, operand);
-        log();
-    }
-
-    @Override
-    public void visitVarInsn(int opcode, int var) {
-        super.visitVarInsn(opcode, var);
-        log();
-    }
-
-    @Override
-    public void visitTypeInsn(int opcode, String type) {
-        super.visitTypeInsn(opcode, type);
-        log();
-    }
-
-    @Override
-    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-        super.visitFieldInsn(opcode, owner, name, desc);
-        log();
-    }
-
-    @Override
-    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-        super.visitMethodInsn(opcode, owner, name, desc);
-        log();
-    }
-
-    @Override
-    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
-        super.visitMethodInsn(opcode, owner, name, desc, itf);
-        log();
-    }
-
-    @Override
-    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
-        super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
-        log();
-    }
-
-    @Override
-    public void visitJumpInsn(int opcode, Label label) {
-        super.visitJumpInsn(opcode, label);
-        log();
-    }
-
-    @Override
-    public void visitLabel(Label label) {
-        super.visitLabel(label);
-        log();
-    }
-
-    @Override
-    public void visitLdcInsn(Object cst) {
-        super.visitLdcInsn(cst);
-        log();
-    }
-
-    @Override
-    public void visitIincInsn(int var, int increment) {
-        super.visitIincInsn(var, increment);
-        log();
-    }
-
-    @Override
-    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
-        super.visitTableSwitchInsn(min, max, dflt, labels);
-        log();
-    }
-
-    @Override
-    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
-        super.visitLookupSwitchInsn(dflt, keys, labels);
-        log();
-    }
-
-    @Override
-    public void visitMultiANewArrayInsn(String desc, int dims) {
-        super.visitMultiANewArrayInsn(desc, dims);
-        log();
-    }
-
-    @Override
-    public Printer visitInsnAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
-        Printer t = super.visitInsnAnnotation(typeRef, typePath, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
-        super.visitTryCatchBlock(start, end, handler, type);
-        log();
-    }
-
-    @Override
-    public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
-        Printer t = super.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
-        super.visitLocalVariable(name, desc, signature, start, end, index);
-        log();
-    }
-
-    @Override
-    public Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) {
-        Printer t = super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitLineNumber(int line, Label start) {
-        super.visitLineNumber(line, start);
-        log();
-    }
-
-    @Override
-    public void visitMaxs(int maxStack, int maxLocals) {
-        super.visitMaxs(maxStack, maxLocals);
-        log();
-    }
-
-    @Override
-    public void visitMethodEnd() {
-        super.visitMethodEnd();
-        log();
-    }
-
-    @Override
-    public Textifier visitAnnotation(String desc, boolean visible) {
-        Textifier t = super.visitAnnotation(desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Textifier visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) {
-        Textifier t = super.visitTypeAnnotation(typeRef, typePath, desc, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public void visitAttribute(Attribute attr) {
-        super.visitAttribute(attr);
-        log();
-    }
-
-    @Override
-    public void visitNestHost(String nestHost) {
-        super.visitNestHost(nestHost);
-        log();
-    }
-
-    @Override
-    public void visitNestMember(String nestMember) {
-        super.visitNestMember(nestMember);
-        log();
-    }
-
-    @Override
-    public void visitMainClass(String mainClass) {
-        super.visitMainClass(mainClass);
-        log();
-    }
-
-    @Override
-    public void visitPackage(String packaze) {
-        super.visitPackage(packaze);
-        log();
-    }
-
-    @Override
-    public void visitOpen(String packaze, int access, String... modules) {
-        super.visitOpen(packaze, access, modules);
-        log();
-    }
-
-    @Override
-    public Textifier visitAnnotableParameterCount(int parameterCount, boolean visible) {
-        Textifier t = super.visitAnnotableParameterCount(parameterCount, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Printer visitRecordComponent(String name, String descriptor, String signature) {
-        Printer p = super.visitRecordComponent(name, descriptor, signature);
-        log();
-        return p;
-    }
-
-    @Override
-    public Textifier visitRecordComponentAnnotation(String descriptor, boolean visible) {
-        Textifier t = super.visitRecordComponentAnnotation(descriptor, visible);
-        log();
-        return t;
-    }
-
-    @Override
-    public Printer visitRecordComponentTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
-        Printer p = super.visitRecordComponentTypeAnnotation(typeRef, typePath, descriptor, visible);
-        log();
-        return p;
-    }
-
-    @Override
-    public void visitRecordComponentAttribute(Attribute attribute) {
-        super.visitRecordComponentAttribute(attribute);
-        log();
-    }
-
-    @Override
-    public void visitRecordComponentEnd() {
-        super.visitRecordComponentEnd();
-        log();
-    }
-
-    @Override
-    public void visitPermittedSubclass(String permittedSubclass) {
-        super.visitPermittedSubclass(permittedSubclass);
-        log();
-    }
-}
diff --git a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
index e6d7dc3..ada7233 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
@@ -20,10 +20,10 @@ package org.codehaus.groovy.control;
 
 import org.apache.groovy.util.Maps;
 import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.control.customizers.CompilationCustomizer;
 import org.codehaus.groovy.control.io.NullWriter;
 import org.codehaus.groovy.control.messages.WarningMessage;
-import org.codehaus.groovy.vmplugin.VMPlugin;
 import org.objectweb.asm.Opcodes;
 
 import java.io.File;
@@ -42,30 +42,15 @@ import java.util.Set;
 import java.util.StringTokenizer;
 
 import static org.apache.groovy.util.SystemUtil.getBooleanSafe;
-import static org.apache.groovy.util.SystemUtil.getIntegerSafe;
 import static org.apache.groovy.util.SystemUtil.getSystemPropertySafe;
 import static org.codehaus.groovy.runtime.StringGroovyMethods.isAtLeast;
+import static org.codehaus.groovy.vmplugin.VMPlugin.getJavaVersion;
 
 /**
  * Compilation control flags and coordination stuff.
  */
 public class CompilerConfiguration {
 
-    /** Optimization Option for enabling <code>invokedynamic</code> compilation. */
-    public static final String INVOKEDYNAMIC = "indy";
-
-    /** Optimization Option for enabling attaching groovydoc as AST node metadata. */
-    public static final String GROOVYDOC = "groovydoc";
-
-    /** Optimization Option for enabling attaching {@link groovy.lang.Groovydoc} annotation. */
-    public static final String RUNTIME_GROOVYDOC = "runtimeGroovydoc";
-
-    /** Optimization Option for enabling parallel parsing. */
-    public static final String PARALLEL_PARSE = "parallelParse";
-
-    /** Joint Compilation Option for enabling generating stubs in memory. */
-    public static final String MEM_STUB = "memStub";
-
     /** This (<code>"1.4"</code>) is the value for targetBytecode to compile for a JDK 1.4. */
     public static final String JDK4 = "1.4";
     /** This (<code>"1.5"</code>) is the value for targetBytecode to compile for a JDK 1.5. */
@@ -77,7 +62,7 @@ public class CompilerConfiguration {
     /** This (<code>"1.8"</code>) is the value for targetBytecode to compile for a JDK 1.8. */
     public static final String JDK8 = "1.8";
     /** This (<code>"9"</code>) is the value for targetBytecode to compile for a JDK 9. */
-    public static final String JDK9 = "9";
+    public static final String JDK9 = "1.9";
     /** This (<code>"10"</code>) is the value for targetBytecode to compile for a JDK 10. */
     public static final String JDK10 = "10";
     /** This (<code>"11"</code>) is the value for targetBytecode to compile for a JDK 11. */
@@ -132,28 +117,152 @@ public class CompilerConfiguration {
             JDK18, Opcodes.V18
     );
 
-    public static final String DEFAULT_TARGET_BYTECODE = defaultTargetBytecode();
-
     /**
      * The valid targetBytecode values.
      */
     public static final String[] ALLOWED_JDKS = JDK_TO_BYTECODE_VERSION_MAP.keySet().toArray(new String[JDK_TO_BYTECODE_VERSION_MAP.size()]);
 
     /**
-     * The ASM API version used when loading/parsing classes and generating proxy adapter classes.
+     * Checks if the specified bytecode version string represents a JDK 1.5+ compatible
+     * bytecode version.
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 1.5+
      */
-    public static final int ASM_API_VERSION = Opcodes.ASM9;
+    public static boolean isPostJDK5(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK5);
+    }
 
     /**
-     * The default source encoding.
+     * Checks if the specified bytecode version string represents a JDK 1.7+ compatible
+     * bytecode version.
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 1.7+
      */
-    public static final String DEFAULT_SOURCE_ENCODING = "UTF-8";
+    public static boolean isPostJDK7(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK7);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 1.8+ compatible
+     * bytecode version.
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 1.8+
+     */
+    public static boolean isPostJDK8(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK8);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 9+ compatible
+     * bytecode version.
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 9+
+     */
+    public static boolean isPostJDK9(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK9);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 10+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 10+
+     */
+    public static boolean isPostJDK10(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK10);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 11+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 11+
+     */
+    public static boolean isPostJDK11(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK11);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 12+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 12+
+     */
+    public static boolean isPostJDK12(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK12);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 13+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 13+
+     */
+    public static boolean isPostJDK13(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK13);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 14+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 14+
+     */
+    public static boolean isPostJDK14(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK14);
+    }
 
     /**
-     *  A convenience for getting a default configuration.  Do not modify it!
-     *  See {@link #CompilerConfiguration(Properties)} for an example on how to
-     *  make a suitable copy to modify.  But if you're really starting from a
-     *  default context, then you probably just want <code>new CompilerConfiguration()</code>.
+     * Checks if the specified bytecode version string represents a JDK 15+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 15+
+     */
+    public static boolean isPostJDK15(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK15);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 16+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 16+
+     */
+    public static boolean isPostJDK16(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK16);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 17+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 17+
+     */
+    public static boolean isPostJDK17(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK17);
+    }
+
+    /**
+     * Checks if the specified bytecode version string represents a JDK 18+ compatible bytecode version.
+     *
+     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
+     * @return true if the bytecode version is JDK 18+
+     */
+    public static boolean isPostJDK18(final String bytecodeVersion) {
+        return isAtLeast(bytecodeVersion, JDK18);
+    }
+
+    //--------------------------------------------------------------------------
+
+    @Deprecated
+    public static final int ASM_API_VERSION = AsmClassGenerator.ASM_API_VERSION;
+
+    /**
+     * The default configuration.
+     * <p>
+     * See {@link #CompilerConfiguration(Properties)} for an example on how to
+     * make a suitable copy to modify. But if you're really starting from some
+     * simple context, then you probably just want {@code new CompilerConfiguration()}.
      */
     public static final CompilerConfiguration DEFAULT = new CompilerConfiguration() {
         @Override
@@ -305,17 +414,27 @@ public class CompilerConfiguration {
         public void setWarningLevel(final int level) {
             throw new UnsupportedOperationException();
         }
+    };
 
-        @Override
-        public void setLogClassgen(boolean logClassgen) {
-            throw new UnsupportedOperationException();
-        }
+    /** The default source encoding. */
+    public static final String DEFAULT_SOURCE_ENCODING = "UTF-8";
 
-        @Override
-        public void setLogClassgenStackTraceMaxDepth(int logClassgenStackTraceMaxDepth) {
-            throw new UnsupportedOperationException();
-        }
-    };
+    /** Optimization Option for enabling attaching groovydoc as AST node metadata. */
+    public static final String GROOVYDOC = "groovydoc";
+
+    /** Optimization Option for enabling <code>invokedynamic</code> compilation. */
+    public static final String INVOKEDYNAMIC = "indy";
+
+    /** Joint Compilation Option for enabling in-memory stub generation. */
+    public static final String MEM_STUB = "memStub";
+
+    /** Optimization Option for enabling parallel parsing. */
+    public static final String PARALLEL_PARSE = "parallelParse";
+
+    /** Optimization Option for enabling attaching {@link groovy.lang.Groovydoc} annotation. */
+    public static final String RUNTIME_GROOVYDOC = "runtimeGroovydoc";
+
+    //--------------------------------------------------------------------------
 
     /**
      * See {@link WarningMessage} for levels.
@@ -323,7 +442,7 @@ public class CompilerConfiguration {
     private int warningLevel;
 
     /**
-     * Encoding for source files
+     * Encoding for source files.
      */
     private String sourceEncoding;
 
@@ -333,109 +452,97 @@ public class CompilerConfiguration {
     private PrintWriter output;
 
     /**
-     * Directory into which to write classes
+     * Directory into which to write classes.
      */
     private File targetDirectory;
 
     /**
-     * Classpath for use during compilation
+     * Classpath for use during compilation.
      */
     private List<String> classpath;
 
     /**
-     * If true, the compiler should produce action information
+     * If true, the compiler should produce action information.
      */
     private boolean verbose;
 
     /**
-     * If true, debugging code should be activated
+     * If true, debugging code should be activated.
      */
     private boolean debug;
 
     /**
-     * If true, generates metadata for reflection on method parameters
+     * If true, generates metadata for reflection on method parameters.
      */
     private boolean parameters;
 
     /**
-     * The number of non-fatal errors to allow before bailing
+     * The number of non-fatal errors to allow before bailing.
      */
     private int tolerance;
 
     /**
-     * Base class name for scripts (must derive from Script)
+     * Base class name for scripts (must derive from Script).
      */
     private String scriptBaseClass;
 
     private ParserPluginFactory pluginFactory;
 
     /**
-     * extension used to find a groovy file
+     * Extension used to find a groovy file.
      */
     private String defaultScriptExtension;
 
     /**
-     * extensions used to find a groovy files
+     * Extensions used to find a groovy files.
      */
     private Set<String> scriptExtensions = new LinkedHashSet<>();
 
     /**
-     * if set to true recompilation is enabled
+     * If set to true recompilation is enabled.
      */
     private boolean recompileGroovySource;
 
     /**
-     * sets the minimum of time after a script can be recompiled.
+     * The minimum of time after a script can be recompiled.
      */
     private int minimumRecompilationInterval;
 
     /**
-     * sets the bytecode version target
+     * The bytecode version target.
      */
     private String targetBytecode;
 
     /**
-     * Whether the bytecode version has preview features enabled (JEP 12)
+     * Whether the bytecode version has preview features enabled (JEP 12).
      */
     private boolean previewFeatures;
 
     /**
-     * Whether logging class generation is enabled
-     */
-    private boolean logClassgen;
-
-    /**
-     * sets logging class generation stack trace max depth
-     */
-    private int logClassgenStackTraceMaxDepth;
-
-    /**
-     * options for joint compilation (null by default == no joint compilation)
+     * Options for joint compilation (null by default == no joint compilation).
      */
     private Map<String, Object> jointCompilationOptions;
 
     /**
-     * options for optimizations (empty map by default)
+     * Options for optimizations (empty map by default).
      */
     private Map<String, Boolean> optimizationOptions;
 
     private final List<CompilationCustomizer> compilationCustomizers = new LinkedList<>();
 
     /**
-     * Global AST transformations which should not be loaded even if they are
-     * defined in META-INF/services/org.codehaus.groovy.transform.ASTTransformation files.
-     * By default, none are disabled.
+     * Global AST transformations which should not be loaded even if defined in
+     * <tt>META-INF/services/org.codehaus.groovy.transform.ASTTransformation</tt>
+     * files. By default, none are disabled.
      */
     private Set<String> disabledGlobalASTTransformations;
 
     private BytecodeProcessor bytecodePostprocessor;
 
-
     /**
      * Sets the compiler flags/settings to default values.
      *
      * The following system properties are referenced when setting the configuration:
-     *
      * <blockquote>
      * <table summary="Groovy Compiler Configuration Properties">
      *   <tr><th>Property Key</th><th>Related Property Getter</th></tr>
@@ -449,11 +556,11 @@ public class CompilerConfiguration {
      * </blockquote>
      *
      * The following system properties are referenced when setting the configuration optimization options:
-     *
      * <blockquote>
-     * <table summary="Groovy Compiler Optimization Options Configuration Properties">
+     * <table summary="Groovy Compiler Optimization Properties">
      *   <tr><th>Property Key</th><th>Related Property Getter</th></tr>
      *   <tr><td><code>groovy.target.indy</code></td><td>{@link #getOptimizationOptions}</td></tr>
+     *   <tr><td><code>groovy.parallel.parse</code></td><td>{@link #getOptimizationOptions}</td></tr>
      *   <tr><td><code>groovy.attach.groovydoc</code></td><td>{@link #getOptimizationOptions}</td></tr>
      *   <tr><td><code>groovy.attach.runtime.groovydoc</code></td><td>{@link #getOptimizationOptions}</td></tr>
      * </table>
@@ -467,25 +574,22 @@ public class CompilerConfiguration {
         warningLevel = WarningMessage.LIKELY_ERRORS;
         parameters = getBooleanSafe("groovy.parameters");
         previewFeatures = getBooleanSafe("groovy.preview.features");
-        logClassgen = getBooleanSafe("groovy.log.classgen");
-        logClassgenStackTraceMaxDepth = getIntegerSafe("groovy.log.classgen.stacktrace.max.depth", 0);
         sourceEncoding = getSystemPropertySafe("groovy.source.encoding",
                 getSystemPropertySafe("file.encoding", DEFAULT_SOURCE_ENCODING));
         setTargetDirectorySafe(getSystemPropertySafe("groovy.target.directory"));
-        setTargetBytecodeIfValid(getSystemPropertySafe("groovy.target.bytecode", DEFAULT_TARGET_BYTECODE));
+        setTargetBytecodeIfValid(getSystemPropertySafe("groovy.target.bytecode", getJavaVersion()));
         defaultScriptExtension = getSystemPropertySafe("groovy.default.scriptExtension", ".groovy");
 
-        optimizationOptions = new HashMap<>(4);
-        handleOptimizationOption(INVOKEDYNAMIC, getSystemPropertySafe("groovy.target.indy", "true"));
-        handleOptimizationOption(GROOVYDOC, getSystemPropertySafe("groovy.attach.groovydoc"));
-        handleOptimizationOption(RUNTIME_GROOVYDOC, getSystemPropertySafe("groovy.attach.runtime.groovydoc"));
-        handleOptimizationOption(PARALLEL_PARSE, getSystemPropertySafe("groovy.parallel.parse", "true"));
-
-        boolean memStubEnabled = Boolean.parseBoolean(getSystemPropertySafe("groovy.mem.stub", "false"));
-        if (memStubEnabled) {
+        if (getBooleanSafe("groovy.mem.stub")) {
             jointCompilationOptions = new HashMap<>(2);
-            jointCompilationOptions.put(MEM_STUB, memStubEnabled);
+            jointCompilationOptions.put(MEM_STUB, Boolean.TRUE);
         }
+
+        optimizationOptions = new HashMap<>(4);
+        handleOptimizationOption(INVOKEDYNAMIC,     getSystemPropertySafe("groovy.target.indy", "true"));
+        handleOptimizationOption(PARALLEL_PARSE,    getSystemPropertySafe("groovy.parallel.parse", "true"));
+        handleOptimizationOption(GROOVYDOC,         getSystemPropertySafe("groovy.attach.groovydoc"));
+        handleOptimizationOption(RUNTIME_GROOVYDOC, getSystemPropertySafe("groovy.attach.runtime.groovydoc"));
     }
 
     private void handleOptimizationOption(String key, String val) {
@@ -521,21 +625,16 @@ public class CompilerConfiguration {
         setMinimumRecompilationInterval(configuration.getMinimumRecompilationInterval());
         setTargetBytecode(configuration.getTargetBytecode());
         setPreviewFeatures(configuration.isPreviewFeatures());
-        setLogClassgen(configuration.isLogClassgen());
-        setLogClassgenStackTraceMaxDepth(configuration.getLogClassgenStackTraceMaxDepth());
         setDefaultScriptExtension(configuration.getDefaultScriptExtension());
         setSourceEncoding(configuration.getSourceEncoding());
         setPluginFactory(configuration.getPluginFactory());
         setDisabledGlobalASTTransformations(configuration.getDisabledGlobalASTTransformations());
         setScriptExtensions(new LinkedHashSet<>(configuration.getScriptExtensions()));
         setOptimizationOptions(new HashMap<>(configuration.getOptimizationOptions()));
+        setJointCompilationOptions(Optional.ofNullable(configuration.getJointCompilationOptions()).map(HashMap::new).orElse(null));
         setBytecodePostprocessor(configuration.getBytecodePostprocessor());
-
-        Map<String, Object> jointCompilationOptions = configuration.getJointCompilationOptions();
-        setJointCompilationOptions(null != jointCompilationOptions ? new HashMap<>(jointCompilationOptions) : jointCompilationOptions);
-
         // TODO GROOVY-9585: add line below once gradle build issues fixed
-//        compilationCustomizers.addAll(configuration.getCompilationCustomizers());
+        //compilationCustomizers.addAll(configuration.getCompilationCustomizers());
     }
 
     /**
@@ -595,136 +694,6 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Checks if the specified bytecode version string represents a JDK 1.5+ compatible
-     * bytecode version.
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 1.5+
-     */
-    public static boolean isPostJDK5(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK5);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 1.7+ compatible
-     * bytecode version.
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 1.7+
-     */
-    public static boolean isPostJDK7(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK7);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 1.8+ compatible
-     * bytecode version.
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 1.8+
-     */
-    public static boolean isPostJDK8(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK8);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 9+ compatible
-     * bytecode version.
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 9+
-     */
-    public static boolean isPostJDK9(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK9);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 10+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 10+
-     */
-    public static boolean isPostJDK10(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK10);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 11+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 11+
-     */
-    public static boolean isPostJDK11(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK11);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 12+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 12+
-     */
-    public static boolean isPostJDK12(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK12);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 13+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 13+
-     */
-    public static boolean isPostJDK13(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK13);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 14+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 14+
-     */
-    public static boolean isPostJDK14(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK14);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 15+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 15+
-     */
-    public static boolean isPostJDK15(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK15);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 16+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 16+
-     */
-    public static boolean isPostJDK16(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK16);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 17+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 17+
-     */
-    public static boolean isPostJDK17(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK17);
-    }
-
-    /**
-     * Checks if the specified bytecode version string represents a JDK 18+ compatible bytecode version.
-     *
-     * @param bytecodeVersion The parameter can take one of the values in {@link #ALLOWED_JDKS}.
-     * @return true if the bytecode version is JDK 18+
-     */
-    public static boolean isPostJDK18(final String bytecodeVersion) {
-        return isAtLeast(bytecodeVersion, JDK18);
-    }
-
-    /**
      * Method to configure a CompilerConfiguration by using Properties.
      * For a list of available properties look at {@link #CompilerConfiguration(Properties)}.
      * @param configuration The properties to get flag values from.
@@ -771,19 +740,6 @@ public class CompilerConfiguration {
         text = configuration.getProperty("groovy.preview.features");
         if (text != null) setPreviewFeatures(text.equalsIgnoreCase("true"));
 
-        text = configuration.getProperty("groovy.log.classgen");
-        if (text != null) setLogClassgen(text.equalsIgnoreCase("true"));
-
-        text = configuration.getProperty("groovy.log.classgen.stacktrace.max.depth");
-        if (text != null) {
-            int logClassgenStackTraceMaxDepth = 0;
-            try {
-                logClassgenStackTraceMaxDepth = Integer.parseInt(text);
-            } catch (Exception ignored) {
-            }
-            setLogClassgenStackTraceMaxDepth(Math.max(logClassgenStackTraceMaxDepth, 0));
-        }
-
         text = configuration.getProperty("groovy.classpath");
         if (text != null) setClasspath(text);
 
@@ -831,7 +787,6 @@ public class CompilerConfiguration {
         }
     }
 
-
     /**
      * Gets the currently configured warning level. See {@link WarningMessage}
      * for level details.
@@ -867,6 +822,7 @@ public class CompilerConfiguration {
 
     /**
      * Gets the currently configured output writer.
+     *
      * @deprecated not used anymore
      */
     @Deprecated
@@ -876,6 +832,7 @@ public class CompilerConfiguration {
 
     /**
      * Sets the output writer.
+     *
      * @deprecated not used anymore, has no effect
      */
     @Deprecated
@@ -992,25 +949,22 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Sets the error tolerance, which is the number of
-     * non-fatal errors (per unit) that should be tolerated before
-     * compilation is aborted.
+     * Sets the error tolerance, which is the number of non-fatal errors (per unit)
+     * that should be tolerated before compilation is aborted.
      */
     public void setTolerance(final int tolerance) {
         this.tolerance = tolerance;
     }
 
     /**
-     * Gets the name of the base class for scripts.  It must be a subclass
-     * of Script.
+     * Gets the name of the base class for scripts.
      */
     public String getScriptBaseClass() {
         return this.scriptBaseClass;
     }
 
     /**
-     * Sets the name of the base class for scripts.  It must be a subclass
-     * of Script.
+     * Sets the name of the base class for scripts. It must be a subclass of {@link groovy.lang.Script}.
      */
     public void setScriptBaseClass(final String scriptBaseClass) {
         this.scriptBaseClass = scriptBaseClass;
@@ -1069,8 +1023,8 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Sets the bytecode compatibility level. The parameter can take one of the values
-     * in {@link #ALLOWED_JDKS}.
+     * Sets the bytecode compatibility level. The parameter can take one of the
+     * values in {@link #ALLOWED_JDKS}.
      *
      * @param version the bytecode compatibility level
      */
@@ -1079,8 +1033,12 @@ public class CompilerConfiguration {
     }
 
     private void setTargetBytecodeIfValid(final String version) {
-        if (JDK_TO_BYTECODE_VERSION_MAP.containsKey(version)) {
-            this.targetBytecode = version;
+        int index = Arrays.binarySearch(ALLOWED_JDKS, !version.startsWith("1") ? "1." + version : version);
+        if (index >= 0) {
+            targetBytecode = ALLOWED_JDKS[index];
+        } else {
+            index = Math.abs(index) - 2; // closest version
+            targetBytecode = ALLOWED_JDKS[Math.max(0, index)];
         }
     }
 
@@ -1091,24 +1049,23 @@ public class CompilerConfiguration {
      * @return bytecode compatibility level
      */
     public String getTargetBytecode() {
-        return this.targetBytecode;
+        return targetBytecode;
     }
 
     /**
-     * Returns the ASM bytecode version
+     * Returns the targeted bytecode (aka Java class file) version number.
      *
-     * @return ASM bytecode version
      * @since 4.0.0
      */
-    public int getBytecodeVersion() {
-        Integer bytecodeVersion = CompilerConfiguration.JDK_TO_BYTECODE_VERSION_MAP.get(targetBytecode);
+    public final int getBytecodeVersion() {
+        Integer bytecodeVersion = JDK_TO_BYTECODE_VERSION_MAP.get(getTargetBytecode());
         if (bytecodeVersion == null) {
-            throw new GroovyBugError("Bytecode version [" + targetBytecode + "] is not supported by the compiler");
+            throw new GroovyBugError("Bytecode version '" + getTargetBytecode() + "' is not supported by the compiler");
         }
 
         if (bytecodeVersion <= Opcodes.V1_8) {
             return Opcodes.V1_8;
-        } else if (previewFeatures) {
+        } else if (isPreviewFeatures()) {
             return bytecodeVersion | Opcodes.V_PREVIEW;
         } else {
             return bytecodeVersion;
@@ -1116,20 +1073,6 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Returns the default target bytecode compatibility level
-     *
-     * @return the default target bytecode compatibility level
-     * @since 4.0.0
-     */
-    private static String defaultTargetBytecode() {
-        final String javaVersion = VMPlugin.getJavaVersion();
-        if (JDK_TO_BYTECODE_VERSION_MAP.containsKey(javaVersion)) {
-            return javaVersion;
-        }
-        return JDK8;
-    }
-
-    /**
      * Whether the bytecode version has preview features enabled (JEP 12)
      *
      * @return preview features
@@ -1148,46 +1091,6 @@ public class CompilerConfiguration {
     }
 
     /**
-     * Returns whether logging class generation is enabled
-     *
-     * @return whether logging class generation is enabled
-     * @since 4.0.0
-     */
-    public boolean isLogClassgen() {
-        return logClassgen;
-    }
-
-    /**
-     * Sets whether logging class generation is enabled
-     *
-     * @param logClassgen whether to enable logging class generation
-     * @since 4.0.0
-     */
-    public void setLogClassgen(boolean logClassgen) {
-        this.logClassgen = logClassgen;
-    }
-
-    /**
-     * Returns stack trace max depth of logging class generation
-     *
-     * @return stack trace max depth of logging class generation
-     * @since 4.0.0
-     */
-    public int getLogClassgenStackTraceMaxDepth() {
-        return logClassgenStackTraceMaxDepth;
-    }
-
-    /**
-     * Sets stack trace max depth of logging class generation
-     *
-     * @param logClassgenStackTraceMaxDepth stack trace max depth of logging class generation
-     * @since 4.0.0
-     */
-    public void setLogClassgenStackTraceMaxDepth(int logClassgenStackTraceMaxDepth) {
-        this.logClassgenStackTraceMaxDepth = logClassgenStackTraceMaxDepth;
-    }
-
-    /**
      * Gets the joint compilation options for this configuration.
      * @return the options
      */
@@ -1239,7 +1142,8 @@ public class CompilerConfiguration {
 
     /**
      * Returns the list of compilation customizers.
-     * @return the customizers (always not null)
+     *
+     * @return the customizers (always non-null)
      */
     public List<CompilationCustomizer> getCompilationCustomizers() {
         return compilationCustomizers;
diff --git a/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java b/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
index 79b6729..22b2d2d 100644
--- a/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
+++ b/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java
@@ -60,7 +60,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 import static org.codehaus.groovy.reflection.ReflectionUtils.isSealed;
 import static org.objectweb.asm.Opcodes.AASTORE;
 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
diff --git a/src/main/java/org/codehaus/groovy/runtime/callsite/GroovySunClassLoader.java b/src/main/java/org/codehaus/groovy/runtime/callsite/GroovySunClassLoader.java
index dcb9bce..ed23a86 100644
--- a/src/main/java/org/codehaus/groovy/runtime/callsite/GroovySunClassLoader.java
+++ b/src/main/java/org/codehaus/groovy/runtime/callsite/GroovySunClassLoader.java
@@ -28,7 +28,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.security.PrivilegedAction;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 
 public class GroovySunClassLoader extends SunClassLoader {
 
diff --git a/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
index d47ed5b..c6a764e 100644
--- a/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java
@@ -92,6 +92,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.runtime.StringGroovyMethods.isAtLeast;
 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
 import static org.objectweb.asm.Opcodes.ACC_FINAL;
 import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
@@ -157,7 +158,7 @@ public class RecordTypeASTTransformation extends AbstractASTTransformation imple
         if (sourceUnit != null) {
             CompilerConfiguration config = sourceUnit.getConfiguration();
             String targetBytecode = config.getTargetBytecode();
-            isPostJDK16 = CompilerConfiguration.isPostJDK16(targetBytecode);
+            isPostJDK16 = isAtLeast(targetBytecode, CompilerConfiguration.JDK16);
             message = "Expecting JDK16+ but found " + targetBytecode;
         }
         boolean isNative = isPostJDK16 && mode != RecordTypeMode.EMULATE;
diff --git a/src/main/java/org/codehaus/groovy/transform/SealedASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/SealedASTTransformation.java
index 04fda04..7692457 100644
--- a/src/main/java/org/codehaus/groovy/transform/SealedASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/SealedASTTransformation.java
@@ -35,6 +35,7 @@ import org.codehaus.groovy.control.SourceUnit;
 import java.util.List;
 
 import static org.codehaus.groovy.ast.ClassHelper.make;
+import static org.codehaus.groovy.runtime.StringGroovyMethods.isAtLeast;
 
 /**
  * Handles generation of code for the @Sealed annotation.
@@ -70,7 +71,7 @@ public class SealedASTTransformation extends AbstractASTTransformation {
             if (sourceUnit != null) {
                 CompilerConfiguration config = sourceUnit.getConfiguration();
                 String targetBytecode = config.getTargetBytecode();
-                isPostJDK17 = CompilerConfiguration.isPostJDK17(targetBytecode);
+                isPostJDK17 = isAtLeast(targetBytecode, CompilerConfiguration.JDK17);
                 message = "Expecting JDK17+ but found " + targetBytecode;
             }
             List<AnnotationNode> annotations = cNode.getAnnotations(SEALED_OPTIONS_TYPE);
diff --git a/src/test/gls/annotations/AnnotationsTestBase.java b/src/test/gls/annotations/AnnotationsTestBase.java
index 1f30a67..e594b49 100644
--- a/src/test/gls/annotations/AnnotationsTestBase.java
+++ b/src/test/gls/annotations/AnnotationsTestBase.java
@@ -30,7 +30,7 @@ import org.objectweb.asm.*;
 import java.util.ArrayList;
 import java.util.List;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 
 public abstract class AnnotationsTestBase extends GroovyTestCase {
     MyLoader loader;
diff --git a/src/test/gls/generics/GenericsTestBase.java b/src/test/gls/generics/GenericsTestBase.java
index 48a24f1..7f1898e 100644
--- a/src/test/gls/generics/GenericsTestBase.java
+++ b/src/test/gls/generics/GenericsTestBase.java
@@ -30,7 +30,7 @@ import org.objectweb.asm.*;
 import java.util.HashMap;
 import java.util.Map;
 
-import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION;
 
 public abstract class GenericsTestBase extends GroovyTestCase {
     MyLoader loader;
diff --git a/src/test/groovy/bugs/Groovy10281.groovy b/src/test/groovy/bugs/Groovy10281.groovy
deleted file mode 100644
index 9f59928..0000000
--- a/src/test/groovy/bugs/Groovy10281.groovy
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package bugs
-
-import groovy.transform.CompileStatic
-import org.codehaus.groovy.control.CompilationUnit
-import org.codehaus.groovy.control.CompilerConfiguration
-import org.codehaus.groovy.control.Phases
-import org.junit.Test
-
-@CompileStatic
-final class Groovy10281 {
-    @Test
-    void testLoggingClassGenWithStacktrace() {
-        def result = logClassGen(true)
-        assert result.contains('// org.codehaus.groovy.classgen.AsmClassGenerator#visitClass:')
-        assert result.contains('public class helloWorld extends groovy/lang/Script {')
-        assert result.contains('LDC "Hello, world!"')
-    }
-
-    @Test
-    void testLoggingClassGenWithoutStacktrace() {
-        def result = logClassGen(false)
-        assert !result.contains('// org.codehaus.groovy.classgen.AsmClassGenerator#visitClass:')
-        assert result.contains('public class helloWorld extends groovy/lang/Script {')
-        assert result.contains('LDC "Hello, world!"')
-    }
-
-    @Test
-    void testLoggingClassGenWithStacktraceWithNoDepth() {
-        def result = logClassGen(true, 0)
-        assert !result.contains('// org.codehaus.groovy.classgen.AsmClassGenerator#visitClass:')
-        assert result.contains('public class helloWorld extends groovy/lang/Script {')
-        assert result.contains('LDC "Hello, world!"')
-    }
-
-    private static String logClassGen(boolean stacktrace, int maxDepth=50) {
-        def code = """
-                println 'Hello, world!'
-            """
-        def result = new StringWriter()
-        PrintWriter pw = new PrintWriter(result)
-        def config = stacktrace ? new CompilerConfiguration(logClassgen: true, logClassgenStackTraceMaxDepth: maxDepth, output: pw)
-                                                    : new CompilerConfiguration(logClassgen: true, output: pw)
-
-        new CompilationUnit(config).with {
-            addSource 'helloWorld.groovy', code
-            compile Phases.CLASS_GENERATION
-        }
-
-        pw.close()
-        return result.toString()
-    }
-}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/AbstractBytecodeTestCase.groovy b/src/test/org/codehaus/groovy/classgen/asm/AbstractBytecodeTestCase.groovy
index 6c8f9c5..14d21ca 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/AbstractBytecodeTestCase.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/AbstractBytecodeTestCase.groovy
@@ -31,6 +31,8 @@ import org.objectweb.asm.util.TraceClassVisitor
 
 import java.security.CodeSource
 
+import static org.codehaus.groovy.classgen.AsmClassGenerator.ASM_API_VERSION
+
 /**
  * Abstract test case to extend to check the instructions we generate in the bytecode of groovy programs.
  */
@@ -112,7 +114,7 @@ abstract class AbstractBytecodeTestCase extends GroovyTestCase {
     InstructionSequence extractSequence(final byte[] bytes, final Map options = [method: 'run']) {
         def out = new StringBuilderWriter()
         def tcv
-        tcv = new TraceClassVisitor(new ClassVisitor(CompilerConfiguration.ASM_API_VERSION) {
+        tcv = new TraceClassVisitor(new ClassVisitor(ASM_API_VERSION) {
             @Override
             MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String... exceptions) {
                 if (options.method == name) {
diff --git a/src/test/org/codehaus/groovy/control/CompilerConfigurationTest.java b/src/test/org/codehaus/groovy/control/CompilerConfigurationTest.java
index 5673552..bd2db35 100644
--- a/src/test/org/codehaus/groovy/control/CompilerConfigurationTest.java
+++ b/src/test/org/codehaus/groovy/control/CompilerConfigurationTest.java
@@ -25,9 +25,11 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.io.File;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Properties;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -63,7 +65,6 @@ public final class CompilerConfigurationTest {
         assertEquals(10, config.getTolerance());
         assertEquals(100, config.getMinimumRecompilationInterval());
         assertEquals(System.getProperty("file.encoding", CompilerConfiguration.DEFAULT_SOURCE_ENCODING), config.getSourceEncoding());
-        assertEquals(CompilerConfiguration.DEFAULT_TARGET_BYTECODE, config.getTargetBytecode());
         assertFalse(config.getRecompileGroovySource());
         assertEquals(Collections.emptyList(), config.getClasspath());
         assertEquals(".groovy", config.getDefaultScriptExtension());
@@ -123,8 +124,6 @@ public final class CompilerConfigurationTest {
         init.addCompilationCustomizers(new ImportCustomizer().addStarImports("groovy.transform"));
         ParserPluginFactory pluginFactory = ParserPluginFactory.antlr4();
         init.setPluginFactory(pluginFactory);
-        init.setLogClassgen(true);
-        init.setLogClassgenStackTraceMaxDepth(100);
 
         assertEquals(WarningMessage.POSSIBLE_ERRORS, init.getWarningLevel());
         assertTrue(init.getDebug());
@@ -144,8 +143,6 @@ public final class CompilerConfigurationTest {
         assertNull(init.getJointCompilationOptions().get(CompilerConfiguration.MEM_STUB));
         assertEquals(pluginFactory, init.getPluginFactory());
         assertEquals(1, init.getCompilationCustomizers().size());
-        assertTrue(init.isLogClassgen());
-        assertEquals(100, init.getLogClassgenStackTraceMaxDepth());
 
         //
 
@@ -166,8 +163,6 @@ public final class CompilerConfigurationTest {
         assertEquals(".jpp", config.getDefaultScriptExtension());
         assertEquals("somevalue", config.getJointCompilationOptions().get("somekey"));
         assertEquals(pluginFactory, config.getPluginFactory());
-        assertTrue(config.isLogClassgen());
-        assertEquals(100, config.getLogClassgenStackTraceMaxDepth());
         // TODO GROOVY-9585: re-enable below assertion once prod code is fixed
 //        assertEquals(1, config.getCompilationCustomizers().size());
     }
@@ -189,8 +184,6 @@ public final class CompilerConfigurationTest {
         init.setClasspath("");
         File targetDirectory = new File("A wandering path");
         init.setTargetDirectory(targetDirectory);
-        init.setLogClassgen(true);
-        init.setLogClassgenStackTraceMaxDepth(100);
         ParserPluginFactory pluginFactory = ParserPluginFactory.antlr4();
         init.setPluginFactory(pluginFactory);
         init.setDefaultScriptExtension(".jpp");
@@ -207,8 +200,6 @@ public final class CompilerConfigurationTest {
         assertFalse(init.getRecompileGroovySource());
         assertEquals(Collections.emptyList(), init.getClasspath());
         assertEquals(targetDirectory, init.getTargetDirectory());
-        assertTrue(init.isLogClassgen());
-        assertEquals(100, init.getLogClassgenStackTraceMaxDepth());
         assertEquals(pluginFactory, init.getPluginFactory());
         assertEquals(".jpp", init.getDefaultScriptExtension());
         assertNull(init.getJointCompilationOptions());
@@ -228,8 +219,6 @@ public final class CompilerConfigurationTest {
         assertFalse(config.getRecompileGroovySource());
         assertEquals(Collections.emptyList(), config.getClasspath());
         assertEquals(targetDirectory, config.getTargetDirectory());
-        assertTrue(config.isLogClassgen());
-        assertEquals(100, config.getLogClassgenStackTraceMaxDepth());
         assertEquals(pluginFactory, config.getPluginFactory());
         assertEquals(".jpp", config.getDefaultScriptExtension());
         assertNull(config.getJointCompilationOptions());
@@ -252,12 +241,6 @@ public final class CompilerConfigurationTest {
             config.setDefaultScriptExtension(".jpp");
         });
         assertThrows(UnsupportedOperationException.class, () -> {
-            config.setLogClassgen(true);
-        });
-        assertThrows(UnsupportedOperationException.class, () -> {
-            config.setLogClassgenStackTraceMaxDepth(100);
-        });
-        assertThrows(UnsupportedOperationException.class, () -> {
             config.setMinimumRecompilationInterval(975);
         });
         assertThrows(UnsupportedOperationException.class, () -> {
@@ -291,4 +274,12 @@ public final class CompilerConfigurationTest {
             config.setWarningLevel(WarningMessage.POSSIBLE_ERRORS);
         });
     }
+
+    @Test // GROOVY-10278
+    public void testTargetVersion() {
+        CompilerConfiguration config = new CompilerConfiguration();
+        String[] inputs = {"1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "5",   "6",   "7",   "8",   "9",   "9.0", "10", "11", "12", "13", "14", "15", "16", "17", "18"};
+        String[] expect = {"1.4", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "1.5", "1.6", "1.7", "1.8", "1.9", "1.9", "10", "11", "12", "13", "14", "15", "16", "17", "18"};
+        assertArrayEquals(expect, Arrays.stream(inputs).map(v -> { config.setTargetBytecode(v); return config.getTargetBytecode(); }).toArray(String[]::new));
+    }
 }
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
index 76a6861..9a37760 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
@@ -307,13 +307,8 @@ public class Groovyc extends MatchingTask {
      *
      * @param version the bytecode compatibility level
      */
-    public void setTargetBytecode(String version) {
-        for (String allowedJdk : CompilerConfiguration.ALLOWED_JDKS) {
-            if (allowedJdk.equals(version)) {
-                this.targetBytecode = version;
-                break;
-            }
-        }
+    public void setTargetBytecode(final String version) {
+        targetBytecode = version;
     }
 
     /**
@@ -322,7 +317,7 @@ public class Groovyc extends MatchingTask {
      * @return bytecode compatibility level. Can be one of the values in {@link CompilerConfiguration#ALLOWED_JDKS}.
      */
     public String getTargetBytecode() {
-        return this.targetBytecode;
+        return targetBytecode;
     }
 
     /**
@@ -1127,7 +1122,9 @@ public class Groovyc extends MatchingTask {
             commandLineList.add("-Xmx" + memoryMaximumSize);
         }
         if (targetBytecode != null) {
-            commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
+            CompilerConfiguration cc = new CompilerConfiguration();
+            cc.setTargetBytecode(targetBytecode); // nearest valid value
+            commandLineList.add("-Dgroovy.target.bytecode=" + cc.getTargetBytecode());
         }
         if (!"*.groovy".equals(getScriptExtension())) {
             String tmpExtension = getScriptExtension();