You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2026/08/11 03:31:55 UTC

(skywalking) branch fix/dsl-inline-fqcn created (now e5998cb1d7)

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

wu-sheng pushed a change to branch fix/dsl-inline-fqcn
in repository https://gitbox.apache.org/repos/asf/skywalking.git


      at e5998cb1d7 Use imports instead of inline fully-qualified names in the DSL compilers

This branch includes the following new commits:

     new e5998cb1d7 Use imports instead of inline fully-qualified names in the DSL compilers

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.



(skywalking) 01/01: Use imports instead of inline fully-qualified names in the DSL compilers

Posted by wu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

wu-sheng pushed a commit to branch fix/dsl-inline-fqcn
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit e5998cb1d7e58548ed12aec5c32c7e62158cfd02
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Tue Aug 11 11:31:45 2026 +0800

    Use imports instead of inline fully-qualified names in the DSL compilers
    
    CLAUDE.md bans fully-qualified class names written inline where an import would
    do, and names the exact form Analyzer.java:242 used: a field declared as
    `private javassist.ClassPool pool;`. 44 such sites across 14 files in the four
    DSL modules -- parameter and field types, locals, throws clauses, static calls, a
    class literal and a method reference.
    
    Every one is a name the COMPILER resolves. Nothing resolved at runtime was
    touched: no FQCN inside a codegen string literal, none in a FreeMarker template,
    none handed to Class.forName or to Javassist. That distinction is the whole risk
    here -- Javassist's compiler has no import statement and resolves simple names
    only against java.lang, so shortening a name in generated source compiles as Java
    and then fails when the rule is compiled.
    
    The transform only rewrote lines containing no quote character, which is sufficient
    rather than merely convenient: a Java string literal cannot span lines under JDK
    11, so a line with no quote cannot be inside one. Simple-name collisions and
    in-file shadowing were checked before any import was added; there were none.
    
    Adds a short CLAUDE.md to code-templates-v2/ saying the templates must stay fully
    qualified. Those files are the weakest spot, because they are not Java and a
    reader editing one has no reason to consult a Java style rule.
---
 .../log/analyzer/v2/compiler/LALBlockCodegen.java  |  9 +++++----
 .../analyzer/v2/compiler/LALClassGenerator.java    | 10 ++++++----
 .../log/analyzer/v2/compiler/LALDefCodegen.java    | 11 ++++++-----
 .../log/analyzer/v2/compiler/LALValueCodegen.java  |  3 ++-
 .../provider/log/listener/LogFilterListener.java   |  3 ++-
 .../skywalking/oap/meter/analyzer/v2/Analyzer.java |  9 +++++----
 .../oap/meter/analyzer/v2/MetricConvert.java       | 11 ++++++-----
 .../analyzer/v2/compiler/MALBytecodeHelper.java    |  3 ++-
 .../analyzer/v2/compiler/MALClassGenerator.java    | 22 +++++++++++++---------
 .../analyzer/v2/compiler/MALClosureCodegen.java    |  5 +++--
 .../analyzer/v2/compiler/MALCodegenHelper.java     |  3 ++-
 .../v2/compiler/rt/MalExtensionRegistry.java       | 13 ++++++++-----
 .../meter/analyzer/v2/prometheus/rule/Rules.java   |  3 ++-
 .../oal/v2/generator/OALClassGeneratorV2.java      |  2 +-
 .../src/main/resources/code-templates-v2/CLAUDE.md | 13 +++++++++++++
 15 files changed, 76 insertions(+), 44 deletions(-)

diff --git a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALBlockCodegen.java b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALBlockCodegen.java
index 54a84bc8ec..8fc2959aea 100644
--- a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALBlockCodegen.java
+++ b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALBlockCodegen.java
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Map;
 import org.apache.skywalking.oap.server.core.analysis.Layer;
 import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;
+import java.lang.reflect.Method;
 
 /**
  * Code generation for LAL block-level structures: {@code extractor},
@@ -250,7 +251,7 @@ final class LALBlockCodegen {
             final LALClassGenerator.GenCtx genCtx) {
         final String[] candidates =
             FIELD_TYPE_SETTER_CANDIDATES[field.getFieldType().ordinal()];
-        java.lang.reflect.Method setter = null;
+        Method setter = null;
         for (final String candidate : candidates) {
             setter = findSetter(genCtx.outputType, candidate);
             if (setter != null) {
@@ -482,7 +483,7 @@ final class LALBlockCodegen {
         }
 
         // Compile-time validation: verify the setter exists on the output type
-        final java.lang.reflect.Method setter = findSetter(genCtx.outputType, setterName);
+        final Method setter = findSetter(genCtx.outputType, setterName);
         if (setter == null) {
             throw new IllegalArgumentException(
                 "Output type " + genCtx.outputType.getName()
@@ -507,11 +508,11 @@ final class LALBlockCodegen {
         sb.append(");\n");
     }
 
-    private static java.lang.reflect.Method findSetter(
+    private static Method findSetter(
             final Class<?> clazz, final String setterName) {
         Class<?> c = clazz;
         while (c != null && c != Object.class) {
-            for (final java.lang.reflect.Method m : c.getDeclaredMethods()) {
+            for (final Method m : c.getDeclaredMethods()) {
                 if (m.getName().equals(setterName)
                         && m.getParameterCount() == 1) {
                     return m;
diff --git a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
index b004cd6bc8..18118827dd 100644
--- a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
+++ b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALClassGenerator.java
@@ -42,6 +42,8 @@ import org.apache.skywalking.oap.log.analyzer.v2.dsl.LalExpression;
 import org.apache.skywalking.oap.server.core.WorkPath;
 import org.apache.skywalking.oap.server.library.util.StringUtil;
 import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;
+import javassist.CannotCompileException;
+import javassist.CtField;
 
 /**
  * Generates {@link LalExpression} implementation classes from
@@ -309,7 +311,7 @@ public final class LALClassGenerator {
      * {@code if (this.debug.isGateOn()) LALDebug.captureXxx(this.debug, ...)} call sites
      * that read the field directly.
      */
-    private void emitDebugHolderMembers(final CtClass ctClass) throws javassist.CannotCompileException {
+    private void emitDebugHolderMembers(final CtClass ctClass) throws CannotCompileException {
         if (!DSLDebugCodegenSwitch.isInjectionEnabled()) {
             // Injection off — fall back to the LalExpression.debugHolder() default
             // (null), no GateHolder field, no probe call sites.
@@ -318,7 +320,7 @@ public final class LALClassGenerator {
         final String escapedContent = DslJavaSourceText.toLiteral(content);
         // Per-rule capture binding — instance field, lowercase per Java
         // convention (it's a final but not a static-final constant).
-        ctClass.addField(javassist.CtField.make(
+        ctClass.addField(CtField.make(
             "public final " + LALCodegenHelper.GATE_HOLDER_FQCN + " debug = new "
                 + LALCodegenHelper.GATE_HOLDER_FQCN + "(\"" + escapedContent + "\");",
             ctClass));
@@ -514,14 +516,14 @@ public final class LALClassGenerator {
      * path so we don't need {@code --add-opens java.base/java.lang} on the OAP container.
      * Same shape as {@code MALClassGenerator}; both DSLs share the contract.
      */
-    private Class<?> defineClass(final CtClass ctClass) throws javassist.CannotCompileException {
+    private Class<?> defineClass(final CtClass ctClass) throws CannotCompileException {
         if (targetClassLoader != null) {
             if (targetClassLoader instanceof BytecodeClassDefiner) {
                 try {
                     return ((BytecodeClassDefiner) targetClassLoader)
                         .defineClass(ctClass.getName(), ctClass.toBytecode());
                 } catch (final IOException e) {
-                    throw new javassist.CannotCompileException(
+                    throw new CannotCompileException(
                         "failed to serialise " + ctClass.getName() + " bytes", e);
                 }
             }
diff --git a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALDefCodegen.java b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALDefCodegen.java
index 994bbb36b0..0373a201db 100644
--- a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALDefCodegen.java
+++ b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALDefCodegen.java
@@ -18,6 +18,7 @@
 package org.apache.skywalking.oap.log.analyzer.v2.compiler;
 
 import java.util.List;
+import java.lang.reflect.Method;
 
 /**
  * Code generation for LAL {@code def} local variable declarations and
@@ -260,7 +261,7 @@ final class LALDefCodegen {
                 final String methodName = ms.getName();
 
                 // Resolve method on currentType via reflection
-                final java.lang.reflect.Method method =
+                final Method method =
                     resolveMethod(currentType, methodName, ms.getArguments());
                 if (method == null) {
                     throw new IllegalArgumentException(
@@ -299,7 +300,7 @@ final class LALDefCodegen {
                 final String getterName = "get"
                     + Character.toUpperCase(fieldName.charAt(0))
                     + fieldName.substring(1);
-                java.lang.reflect.Method getter = null;
+                Method getter = null;
                 try {
                     getter = currentType.getMethod(getterName);
                 } catch (NoSuchMethodException e) {
@@ -337,7 +338,7 @@ final class LALDefCodegen {
             } else if (seg instanceof LALScriptModel.IndexSegment) {
                 final int index = ((LALScriptModel.IndexSegment) seg).getIndex();
                 // Try get(int) method (e.g., JsonArray.get(int))
-                java.lang.reflect.Method getMethod = null;
+                Method getMethod = null;
                 try {
                     getMethod = currentType.getMethod("get", int.class);
                 } catch (NoSuchMethodException e) {
@@ -367,7 +368,7 @@ final class LALDefCodegen {
      * For methods with String arguments (like JsonObject.get(String)),
      * prioritizes exact match by parameter types.
      */
-    private static java.lang.reflect.Method resolveMethod(
+    private static Method resolveMethod(
             final Class<?> type, final String name,
             final List<LALScriptModel.FunctionArg> args) {
         final int argCount = args != null ? args.size() : 0;
@@ -392,7 +393,7 @@ final class LALDefCodegen {
             }
         }
         // Fallback: find by name and arg count
-        for (final java.lang.reflect.Method m : type.getMethods()) {
+        for (final Method m : type.getMethods()) {
             if (m.getName().equals(name)
                     && m.getParameterCount() == argCount) {
                 return m;
diff --git a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALValueCodegen.java b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALValueCodegen.java
index 6e69e6618b..e20a4dd205 100644
--- a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALValueCodegen.java
+++ b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALValueCodegen.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.apache.skywalking.oap.server.core.source.LogMetadata;
 import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;
+import java.lang.reflect.Method;
 
 /**
  * Code generation for LAL expression evaluation: value access, conditions,
@@ -1113,7 +1114,7 @@ final class LALValueCodegen {
             final String getterName = "get" + Character.toUpperCase(field.charAt(0))
                 + field.substring(1);
 
-            final java.lang.reflect.Method getter;
+            final Method getter;
             try {
                 getter = currentType.getMethod(getterName);
             } catch (NoSuchMethodException e) {
diff --git a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/provider/log/listener/LogFilterListener.java b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/provider/log/listener/LogFilterListener.java
index a72944c0c9..2e36b76771 100644
--- a/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/provider/log/listener/LogFilterListener.java
+++ b/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/provider/log/listener/LogFilterListener.java
@@ -48,6 +48,7 @@ import org.apache.skywalking.oap.server.core.source.LogMetadata;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.module.ModuleStartException;
 import org.apache.skywalking.oap.server.library.module.Service;
+import javassist.ClassPool;
 
 /**
  * Runtime listener that executes compiled LAL rules against incoming log data.
@@ -284,7 +285,7 @@ public class LogFilterListener implements LogAnalysisListener {
          * {@code RuleClassLoader} it creates on every compile.
          */
         public CompiledLAL compile(final LALConfig c,
-                                   final javassist.ClassPool pool,
+                                   final ClassPool pool,
                                    final ClassLoader targetClassLoader) throws ModuleStartException {
             final boolean isAuto = LALConfig.LAYER_AUTO.equalsIgnoreCase(c.getLayer());
             final Layer layer = isAuto ? null : Layer.nameOf(c.getLayer());
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/Analyzer.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/Analyzer.java
index 23f99b6d9b..6638408398 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/Analyzer.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/Analyzer.java
@@ -73,6 +73,7 @@ import static java.util.Objects.requireNonNull;
 import static java.util.stream.Collectors.groupingBy;
 import static java.util.stream.Collectors.mapping;
 import static java.util.stream.Collectors.toList;
+import javassist.ClassPool;
 
 /**
  * Analyzer analyses DSL expression with input samples, then to generate meter-system metrics.
@@ -155,7 +156,7 @@ public class Analyzer {
                                  final String expression,
                                  final MeterSystem meterSystem,
                                  final DslSourceRef sourceRef,
-                                 final javassist.ClassPool pool,
+                                 final ClassPool pool,
                                  final ClassLoader targetClassLoader) {
         final Analyzer analyzer = prepare(
             metricName, filter, expression, meterSystem, sourceRef, pool, targetClassLoader);
@@ -179,7 +180,7 @@ public class Analyzer {
                                     final String expression,
                                     final MeterSystem meterSystem,
                                     final DslSourceRef sourceRef,
-                                    final javassist.ClassPool pool,
+                                    final ClassPool pool,
                                     final ClassLoader targetClassLoader) {
         // Static boot / default path: create-if-absent. Runtime-rule on-demand apply passes
         // withSchemaChange() via the explicit-opt overload.
@@ -197,7 +198,7 @@ public class Analyzer {
                                     final String expression,
                                     final MeterSystem meterSystem,
                                     final DslSourceRef sourceRef,
-                                    final javassist.ClassPool pool,
+                                    final ClassPool pool,
                                     final ClassLoader targetClassLoader,
                                     final StorageManipulationOpt storageOpt) {
         Expression e = DSL.parse(metricName, expression, sourceRef, pool, targetClassLoader);
@@ -239,7 +240,7 @@ public class Analyzer {
     private int[] percentiles;
 
     /** Per-file Javassist pool for runtime-rule hot-update, null on startup path. */
-    private javassist.ClassPool pool;
+    private ClassPool pool;
     /** Per-file target classloader for runtime-rule hot-update, null on startup path. */
     private ClassLoader targetClassLoader;
     /**
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/MetricConvert.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/MetricConvert.java
index d514dc1b51..d3f0e83cf3 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/MetricConvert.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/MetricConvert.java
@@ -42,6 +42,7 @@ import org.apache.skywalking.oap.server.core.dsl.debug.GateHolder;
 import org.apache.skywalking.oap.server.core.storage.model.StorageManipulationOpt;
 
 import static java.util.stream.Collectors.toList;
+import javassist.ClassPool;
 
 /**
  * MetricConvert converts {@link SampleFamily} collection to meter-system metrics, then store them to backend storage.
@@ -89,7 +90,7 @@ public class MetricConvert {
     }
 
     public MetricConvert(final MetricRuleConfig rule, final MeterSystem service,
-                         final javassist.ClassPool pool,
+                         final ClassPool pool,
                          final ClassLoader targetClassLoader) {
         this(rule, service, pool, targetClassLoader,
              StorageManipulationOpt.schemaCreateIfAbsent());
@@ -106,7 +107,7 @@ public class MetricConvert {
      *                   peer-node passes withoutSchemaChange to skip server DDL
      */
     public MetricConvert(final MetricRuleConfig rule, final MeterSystem service,
-                         final javassist.ClassPool pool,
+                         final ClassPool pool,
                          final ClassLoader targetClassLoader,
                          final StorageManipulationOpt storageOpt) {
         Preconditions.checkState(!Strings.isNullOrEmpty(rule.getMetricPrefix()));
@@ -244,7 +245,7 @@ public class MetricConvert {
                            final String exp,
                            final MeterSystem service,
                            final DslSourceRef sourceRef,
-                           final javassist.ClassPool pool,
+                           final ClassPool pool,
                            final ClassLoader targetClassLoader) {
         return Analyzer.build(
             metricsName,
@@ -274,7 +275,7 @@ public class MetricConvert {
                               final String exp,
                               final MeterSystem service,
                               final DslSourceRef sourceRef,
-                              final javassist.ClassPool pool,
+                              final ClassPool pool,
                               final ClassLoader targetClassLoader,
                               final StorageManipulationOpt storageOpt) {
         return Analyzer.prepare(
@@ -290,7 +291,7 @@ public class MetricConvert {
     }
 
     private static FilterExpression buildFilter(final MetricRuleConfig rule,
-                                                final javassist.ClassPool pool,
+                                                final ClassPool pool,
                                                 final ClassLoader targetClassLoader) {
         final String filterText = rule.getFilter();
         if (Strings.isNullOrEmpty(filterText)) {
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALBytecodeHelper.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALBytecodeHelper.java
index dc44de7bc5..af67a2d1ea 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALBytecodeHelper.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALBytecodeHelper.java
@@ -32,6 +32,7 @@ import javassist.bytecode.ConstPool;
 import javassist.bytecode.CodeAttribute;
 import javassist.bytecode.MethodInfo;
 import lombok.extern.slf4j.Slf4j;
+import javassist.bytecode.CodeIterator;
 
 /**
  * Javassist bytecode utilities for MAL-generated classes.
@@ -193,7 +194,7 @@ final class MALBytecodeHelper {
             int boundary = 0;
             boolean nextIsNewLine = true;
 
-            final javassist.bytecode.CodeIterator ci = code.iterator();
+            final CodeIterator ci = code.iterator();
             while (ci.hasNext()) {
                 final int pc = ci.next();
                 if (nextIsNewLine) {
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClassGenerator.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClassGenerator.java
index abbee709e2..2a97b9a6cc 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClassGenerator.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClassGenerator.java
@@ -38,6 +38,10 @@ import org.apache.skywalking.oap.meter.analyzer.v2.dsl.MalFilter;
 import org.apache.skywalking.oap.server.core.WorkPath;
 import org.apache.skywalking.oap.server.library.util.StringUtil;
 import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;
+import javassist.CannotCompileException;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.LoaderClassPath;
 
 /**
  * Public API for compiling MAL expressions into {@link MalExpression} implementation classes.
@@ -85,7 +89,7 @@ public final class MALClassGenerator {
     private static ClassPool createClassPool() {
         final ClassPool pool = new ClassPool(true);
         pool.appendClassPath(
-            new javassist.LoaderClassPath(
+            new LoaderClassPath(
                 Thread.currentThread().getContextClassLoader()));
         return pool;
     }
@@ -212,7 +216,7 @@ public final class MALClassGenerator {
         final List<String> params = closure.getParams();
         final String paramName = params.isEmpty() ? "it" : params.get(0);
 
-        final javassist.CtMethod testMethod =
+        final CtMethod testMethod =
             CtNewMethod.make(filterBody, ctClass);
         ctClass.addMethod(testMethod);
         DslGeneratedFileWriter.addLocalVariableTable(testMethod, className,
@@ -260,14 +264,14 @@ public final class MALClassGenerator {
      * requirement on JDK 17+. Otherwise we fall back to the legacy 2-arg toClass for
      * back-compat, but no shipped loader uses that path today.
      */
-    private Class<?> defineClass(final CtClass ctClass) throws javassist.CannotCompileException {
+    private Class<?> defineClass(final CtClass ctClass) throws CannotCompileException {
         if (targetClassLoader != null) {
             if (targetClassLoader instanceof BytecodeClassDefiner) {
                 try {
                     return ((BytecodeClassDefiner) targetClassLoader)
                         .defineClass(ctClass.getName(), ctClass.toBytecode());
                 } catch (final IOException e) {
-                    throw new javassist.CannotCompileException(
+                    throw new CannotCompileException(
                         "failed to serialise " + ctClass.getName() + " bytes", e);
                 }
             }
@@ -314,7 +318,7 @@ public final class MALClassGenerator {
         }
 
         for (int i = 0; i < closures.size(); i++) {
-            ctClass.addField(javassist.CtField.make(
+            ctClass.addField(CtField.make(
                 "public static final " + closureInterfaceTypes.get(i) + " "
                     + closureFieldNames.get(i) + ";", ctClass));
         }
@@ -358,7 +362,7 @@ public final class MALClassGenerator {
         }
 
         // 5. Add methods and bytecode attributes
-        final javassist.CtMethod runMethod =
+        final CtMethod runMethod =
             CtNewMethod.make(runBody, ctClass);
         ctClass.addMethod(runMethod);
         bytecodeHelper.addRunLocalVariableTable(
@@ -372,7 +376,7 @@ public final class MALClassGenerator {
             MalGeneratedSourceLines.statementLinesOf(runBody),
             DslGeneratedFileWriter.lineOfMethod(expressionSource, "run"));
 
-        final javassist.CtMethod metaMethod =
+        final CtMethod metaMethod =
             CtNewMethod.make(metadataBody, ctClass);
         ctClass.addMethod(metaMethod);
         DslGeneratedFileWriter.addLocalVariableTable(metaMethod, className,
@@ -437,7 +441,7 @@ public final class MALClassGenerator {
      * call sites that read the field directly. The constructor arg is the
      * configured {@link #content}, escaped as a Java string literal.
      */
-    private void emitDebugHolderMembers(final CtClass ctClass) throws javassist.CannotCompileException {
+    private void emitDebugHolderMembers(final CtClass ctClass) throws CannotCompileException {
         if (!org.apache.skywalking.oap.server.core.dsl.debug.DSLDebugCodegenSwitch.isInjectionEnabled()) {
             // Injection off — generated class inherits MalExpression.debugHolder()'s
             // default null return, no GateHolder field is emitted, and the captureXxx
@@ -449,7 +453,7 @@ public final class MALClassGenerator {
         final String escapedContent = DslJavaSourceText.toLiteral(content);
         // Per-rule capture binding — instance field, lowercase per Java
         // convention (it's a final but not a static-final constant).
-        ctClass.addField(javassist.CtField.make(
+        ctClass.addField(CtField.make(
             "public final " + holderFqcn + " debug = new " + holderFqcn
                 + "(\"" + escapedContent + "\");",
             ctClass));
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClosureCodegen.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClosureCodegen.java
index 4ee0bd47d1..724383ab06 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClosureCodegen.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALClosureCodegen.java
@@ -25,6 +25,7 @@ import javassist.CtNewConstructor;
 import javassist.CtNewMethod;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;
+import javassist.CtMethod;
 
 /**
  * Generates closure classes for MAL expressions using Javassist bytecode generation.
@@ -625,7 +626,7 @@ final class MALClosureCodegen {
         if (log.isDebugEnabled()) {
             log.debug("Companion class [{}] apply():\n{}", companionName, methodBody);
         }
-        final javassist.CtMethod m = CtNewMethod.make(methodBody, companion);
+        final CtMethod m = CtNewMethod.make(methodBody, companion);
         companion.addMethod(m);
         addCompanionLocalVariableTable(m, info);
         // A companion is its own class file, so it carries its own coordinates: its own .java and
@@ -717,7 +718,7 @@ final class MALClosureCodegen {
         return sb.toString();
     }
 
-    private void addCompanionLocalVariableTable(final javassist.CtMethod m,
+    private void addCompanionLocalVariableTable(final CtMethod m,
                                                 final ClosureInfo info) {
         final List<String> params = info.closure.getParams();
         if (MALCodegenHelper.FOR_EACH_FUNCTION_TYPE.equals(info.interfaceType)) {
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALCodegenHelper.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALCodegenHelper.java
index c66a0e2502..770be8157b 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALCodegenHelper.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALCodegenHelper.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.skywalking.oap.server.core.dsl.debug.DSLDebugCodegenSwitch;
 import org.apache.skywalking.oap.server.core.dsl.DslJavaSourceText;
+import java.lang.reflect.Method;
 
 /**
  * Static utility methods and constants shared across MAL code generation classes.
@@ -231,7 +232,7 @@ final class MALCodegenHelper {
         if (lastMethodName == null) {
             return false;
         }
-        for (final java.lang.reflect.Method m : String.class.getMethods()) {
+        for (final Method m : String.class.getMethods()) {
             if (m.getName().equals(lastMethodName)
                     && m.getReturnType() == boolean.class) {
                 return true;
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java
index b51e40589d..8a2268983c 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java
@@ -28,6 +28,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.oap.meter.analyzer.v2.dsl.SampleFamily;
 import org.apache.skywalking.oap.meter.analyzer.v2.spi.MALContextFunction;
 import org.apache.skywalking.oap.meter.analyzer.v2.spi.MalFunctionExtension;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
 
 /**
  * Compile-time registry for MAL extension functions discovered via SPI.
@@ -92,12 +95,12 @@ public final class MalExtensionRegistry {
             final Class<?>[] extraParamTypes = new Class<?>[paramTypes.length - 1];
             System.arraycopy(paramTypes, 1, extraParamTypes, 0, extraParamTypes.length);
             // Validate List params use List<String> (the only List type MAL supports)
-            final java.lang.reflect.Type[] genericTypes = m.getGenericParameterTypes();
+            final Type[] genericTypes = m.getGenericParameterTypes();
             for (int i = 1; i < genericTypes.length; i++) {
-                if (java.util.List.class.isAssignableFrom(extraParamTypes[i - 1])
-                        && genericTypes[i] instanceof java.lang.reflect.ParameterizedType) {
-                    final java.lang.reflect.Type elementType =
-                        ((java.lang.reflect.ParameterizedType) genericTypes[i])
+                if (List.class.isAssignableFrom(extraParamTypes[i - 1])
+                        && genericTypes[i] instanceof ParameterizedType) {
+                    final Type elementType =
+                        ((ParameterizedType) genericTypes[i])
                             .getActualTypeArguments()[0];
                     if (!String.class.equals(elementType)) {
                         throw new IllegalArgumentException(
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java
index 48de97fcd0..58cabca981 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java
@@ -44,6 +44,7 @@ import org.apache.skywalking.oap.server.library.util.ResourceUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.yaml.snakeyaml.Yaml;
+import java.util.Objects;
 
 /**
  * Rules is factory to instance {@link Rule} from a local file.
@@ -143,7 +144,7 @@ public class Rules {
 
         return merged.entrySet().stream()
             .map(e -> parseRule(path, e.getKey(), diskPaths.get(e.getKey()), e.getValue()))
-            .filter(java.util.Objects::nonNull)
+            .filter(Objects::nonNull)
             .collect(Collectors.toList());
     }
 
diff --git a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2.java b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2.java
index dbca51057a..d695f93238 100644
--- a/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2.java
+++ b/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/v2/generator/OALClassGeneratorV2.java
@@ -471,7 +471,7 @@ public class OALClassGeneratorV2 {
                     // stamped with {ruleName, sourceLine} at instance-init time
                     // — the dsl-debugging records carry a structured per-rule
                     // envelope alongside the verbatim dsl source.
-                    dispatcherClass.addField(javassist.CtField.make(
+                    dispatcherClass.addField(CtField.make(
                         "public final " + holderFqcn + " debug_" + metric.getTableName()
                             + " = " + holderFqcn + ".withMetadata(\""
                             + perMetricContent + "\", \""
diff --git a/oap-server/oal-rt/src/main/resources/code-templates-v2/CLAUDE.md b/oap-server/oal-rt/src/main/resources/code-templates-v2/CLAUDE.md
new file mode 100644
index 0000000000..f8dd2b75cf
--- /dev/null
+++ b/oap-server/oal-rt/src/main/resources/code-templates-v2/CLAUDE.md
@@ -0,0 +1,13 @@
+# OAL code templates — always fully qualify
+
+These `.ftl` files render **generated Java source**, compiled by Javassist, not javac.
+
+**Javassist's compiler has no `import` statement.** It resolves a simple class name only against
+`ClassPool.importedPackages`, which holds `java.lang` and nothing else. So every class named here
+must be fully qualified — `java.util.Map`, `org.apache.skywalking...GateHolder`, all of it.
+
+Shortening one to look tidier still renders, still compiles the surrounding Java, and then fails at
+runtime when the rule is compiled. The project's "no inline fully-qualified class names" rule is
+about hand-written Java and does not apply to this directory.
+
+Same rule for FQCNs inside codegen string literals in the MAL / LAL / Hierarchy generators.