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

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new de152fa58 fix: avoid NoClassDefFoundError in 
supportCodegenForJavaSerialization (#3424)
de152fa58 is described below

commit de152fa5809cb4c336307af4f2c938f3265ccc4f
Author: Sergiy Yevtushenko <[email protected]>
AuthorDate: Thu Feb 26 01:04:46 2026 +0100

    fix: avoid NoClassDefFoundError in supportCodegenForJavaSerialization 
(#3424)
    
    ## Summary
    
    `CodegenSerializer.supportCodegenForJavaSerialization()` calls
    `cls.getEnclosingClass()` before checking `Modifier.isStatic()`. In
    classloader-isolated environments (OSGi, custom module systems with
    per-module classloaders), the enclosing class may not be visible from
    the class's classloader, causing `NoClassDefFoundError`.
    
    **Two issues fixed:**
    
    1. **Evaluation order**: Check `Modifier.isStatic()` first — static
    nested classes support codegen regardless of enclosing class visibility,
    so there is no need to load it.
    
    2. **Error handling**: When `getEnclosingClass()` throws, return `false`
    instead of re-throwing as `RuntimeException`. If the enclosing class
    cannot be loaded, the class cannot function as a non-static inner class
    in this context, so codegen is simply not applicable.
    
    ## Reproduction scenario
    
    - Class `Outer.InnerRecord` is a static nested record
    - `InnerRecord` is loaded by ClassLoader A
    - `Outer` is only visible to ClassLoader B
    - Current code: `getEnclosingClass()` → `NoClassDefFoundError` →
    `RuntimeException` (crash)
    - Fixed code: `isStatic()` → `true` (correct result, no class loading)
---
 .../java/org/apache/fory/resolver/ClassResolver.java    |  4 ++--
 .../org/apache/fory/serializer/CodegenSerializer.java   | 17 +++++++++++------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git 
a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java 
b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
index ca6133a7b..e29ba82fb 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
@@ -1193,7 +1193,7 @@ public class ClassResolver extends TypeResolver {
   @Override
   public Class<? extends Serializer> getSerializerClass(Class<?> cls) {
     boolean codegen =
-        supportCodegenForJavaSerialization(cls) && 
fory.getConfig().isCodeGenEnabled();
+        fory.getConfig().isCodeGenEnabled() && 
supportCodegenForJavaSerialization(cls);
     return getSerializerClass(cls, codegen);
   }
 
@@ -1341,7 +1341,7 @@ public class ClassResolver extends TypeResolver {
   public Class<? extends Serializer> getObjectSerializerClass(
       Class<?> cls, JITContext.SerializerJITCallback<Class<? extends 
Serializer>> callback) {
     boolean codegen =
-        supportCodegenForJavaSerialization(cls) && 
fory.getConfig().isCodeGenEnabled();
+        fory.getConfig().isCodeGenEnabled() && 
supportCodegenForJavaSerialization(cls);
     return getObjectSerializerClass(cls, false, codegen, callback);
   }
 
diff --git 
a/java/fory-core/src/main/java/org/apache/fory/serializer/CodegenSerializer.java
 
b/java/fory-core/src/main/java/org/apache/fory/serializer/CodegenSerializer.java
index 841bec046..e10116c4c 100644
--- 
a/java/fory-core/src/main/java/org/apache/fory/serializer/CodegenSerializer.java
+++ 
b/java/fory-core/src/main/java/org/apache/fory/serializer/CodegenSerializer.java
@@ -32,14 +32,19 @@ import org.apache.fory.memory.MemoryBuffer;
 public final class CodegenSerializer {
 
   public static boolean supportCodegenForJavaSerialization(Class<?> cls) {
-    // bean class can be static nested class, but can't be a non-static inner 
class
-    // If a class is a static class, the enclosing class must not be null.
-    // If enclosing class is null, it must not be a static class.
+    // bean class can be static nested class, but can't be a non-static inner 
class.
+    // Check modifiers first to avoid loading the enclosing class 
unnecessarily —
+    // in classloader-isolated environments (e.g. OSGi, module systems) the 
enclosing
+    // class may not be visible, causing NoClassDefFoundError.
+    if (Modifier.isStatic(cls.getModifiers())) {
+      return true;
+    }
     try {
-      return cls.getEnclosingClass() == null || 
Modifier.isStatic(cls.getModifiers());
-
+      return cls.getEnclosingClass() == null;
     } catch (Throwable t) {
-      throw new RuntimeException(t);
+      // Enclosing class is not loadable — the class cannot be a valid 
non-static
+      // inner class in this context, so codegen is not applicable.
+      return false;
     }
   }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to