From 8614f8bab7b779199d2864c72860e6471d5ba1c9 Mon Sep 17 00:00:00 2001 From: Sergiy Yevtushenko Date: Wed, 25 Feb 2026 23:12:05 +0100 Subject: [PATCH 1/2] fix: avoid NoClassDefFoundError in supportCodegenForJavaSerialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check Modifier.isStatic() before calling getEnclosingClass() to avoid loading the enclosing class unnecessarily. In classloader-isolated environments (OSGi, custom module systems), the enclosing class may not be visible from the current classloader, causing NoClassDefFoundError. Also return false instead of re-throwing when the enclosing class cannot be loaded — if the enclosing class is not resolvable, the class cannot be a valid non-static inner class in this context. --- .../fory/serializer/CodegenSerializer.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) 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 841bec0466..e10116c4c1 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 @@ 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; } } From f56c1e231951144e217e1e63dd172ca12f409dcb Mon Sep 17 00:00:00 2001 From: Sergiy Yevtushenko Date: Wed, 25 Feb 2026 23:17:13 +0100 Subject: [PATCH 2/2] fix: check isCodeGenEnabled() before supportCodegenForJavaSerialization() Swap evaluation order so that when codegen is disabled, supportCodegenForJavaSerialization() is never called. This avoids triggering getEnclosingClass() in classloader-isolated environments where withCodegen(false) should completely bypass codegen logic. Both call sites in getSerializerClass() and getObjectSerializerClass() had the same issue. --- .../src/main/java/org/apache/fory/resolver/ClassResolver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 ca6133a7bb..e29ba82fbd 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 Serializer getRawSerializer(Class cls) { @Override public Class getSerializerClass(Class cls) { boolean codegen = - supportCodegenForJavaSerialization(cls) && fory.getConfig().isCodeGenEnabled(); + fory.getConfig().isCodeGenEnabled() && supportCodegenForJavaSerialization(cls); return getSerializerClass(cls, codegen); } @@ -1341,7 +1341,7 @@ public Object id() { public Class getObjectSerializerClass( Class cls, JITContext.SerializerJITCallback> callback) { boolean codegen = - supportCodegenForJavaSerialization(cls) && fory.getConfig().isCodeGenEnabled(); + fory.getConfig().isCodeGenEnabled() && supportCodegenForJavaSerialization(cls); return getObjectSerializerClass(cls, false, codegen, callback); }