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:25 UTC

[groovy] branch GROOVY-10278 created (now e7f5403)

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

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


      at e7f5403  GROOVY-10278, GROOVY-10281: refactor `CompilerConfiguration` somewhat

This branch includes the following new commits:

     new e7f5403  GROOVY-10278, GROOVY-10281: refactor `CompilerConfiguration` somewhat

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


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

Posted by em...@apache.org.
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();