thmd opened a new issue, #4017:
URL: https://github.com/apache/fory/issues/4017

   ### Search before asking
   
   - [x] I had searched in the [issues](https://github.com/apache/fory/issues) 
and found no similar issues.
   
   
   ### Version
   
   ```
   Fory 1.6.1 and 1.7.0 (latest). Fails on Java 8, passes on Java 21.
   fory-core declares maven.compiler.source/target = 8, so Java 8 is a 
supported target.
   
   Failing JDK : 1.8.0_491-b10, HotSpot 64-Bit Server VM 25.491-b10
   Passing JDK : Temurin 21.0.11+10-LTS
   OS          : macOS 15 (Darwin 24.6.0), arm64
   ```
   
   
   ### Component(s)
   
   Java
   
   ### Minimal reproduce step
   
   
[fory-multi-instance-repro.zip](https://github.com/user-attachments/files/31758009/fory-multi-instance-repro.zip)
   
   On Java 8, constructing a **second** `Fory` instance in the same JVM fails, 
once an earlier
   instance has serialized an object graph large enough to trigger JIT codegen. 
The failure comes
   from `ClassResolver.initialize()` while registering Fory's **own built-in 
types** — the string
   it fails to encode is the package or type name of a Fory internal class, 
which is ASCII by
   construction.
   
   A single `Fory` instance never fails, at any payload size (checked to ~3.3 
MB / 150k objects),
   so this is not a serialization-size problem. Once it throws, every later 
`Fory` construction in
   that JVM fails the same way.
   
   The practical impact is on any application holding more than one `Fory` — 
two library modules
   that each keep a `static` instance, or one instance per classloader in a 
container. The second
   can become permanently un-constructible depending on what the first happened 
to serialize.
   
   The attached `fory-multi-instance-repro.zip` is a single self-contained 
file, no dependencies
   beyond `fory-core`:
   
       unzip fory-multi-instance-repro.zip && cd fory-multi-instance-repro
       curl -sO 
https://repo1.maven.org/maven2/org/apache/fory/fory-core/1.7.0/fory-core-1.7.0.jar
       javac -cp fory-core-1.7.0.jar ForyMultiInstanceRepro.java
       java  -cp fory-core-1.7.0.jar:. ForyMultiInstanceRepro
   
   Optional args: `[items] [instances] [builderConfig]`, defaults `800 4 
copy+num`.
   
   Some configurations are probabilistic, so run it a few times to see a rate:
   
       for i in $(seq 1 10); do java -cp fory-core-1.7.0.jar:. 
ForyMultiInstanceRepro; done
   
   ### What did you expect to see?
   
   OK  items=800 instances=4 bytes=194341
   
   
   ### What did you see instead?
   
   ```
   10 of 10 runs fail on Java 8; 0 of 10 on Java 21.
   
   FAIL at instance 2 of 4 (items=800, bytes=194341): 
java.lang.IllegalArgumentException: Non-ASCII characters in meta string are not 
allowed
   
   java.lang.IllegalArgumentException: Non-ASCII characters in meta string are 
not allowed
        at 
org.apache.fory.meta.MetaStringEncoder.encodeBinary(MetaStringEncoder.java:92)
        at 
org.apache.fory.resolver.SharedRegistry.getEncodedMetaString(SharedRegistry.java:337)
        at 
org.apache.fory.resolver.SharedRegistry.getPackageEncodedMetaString(SharedRegistry.java:309)
        at org.apache.fory.resolver.TypeInfo.<init>(TypeInfo.java:106)
        at 
org.apache.fory.resolver.ClassResolver.registerInternalImpl(ClassResolver.java:728)
        at 
org.apache.fory.resolver.ClassResolver.registerInternal(ClassResolver.java:716)
        at 
org.apache.fory.resolver.ClassResolver.initialize(ClassResolver.java:273)
        at org.apache.fory.Fory.<init>(Fory.java:155)
        at org.apache.fory.config.ForyBuilder.newFory(ForyBuilder.java:789)
        at org.apache.fory.ThreadLocalFory.newFory(ThreadLocalFory.java:67)
   
   Variations across runs of the same command, all with the above root cause:
   
     - it also fails via getTypeNameEncodedMetaString 
(SharedRegistry.java:317), so either meta
       string can be the one that fails;
     - on 1.7.0 it is sometimes surfaced wrapped, as
       org.apache.fory.exception.SerializationException: 
java.lang.RuntimeException: Create sequential serializer failed
       (7/10 raw, 3/10 wrapped in one sample of 10);
     - the failing instance index is usually 2, occasionally 3.
   
   Results, 10 runs per cell:
   
     fory    items  instances  Java 8         Java 21
     1.6.1   800    4          10/10 fail     0/10
     1.7.0   800    4          10/10 fail     0/10
     1.6.1   800    1          0/10           0/10
   ```
   
   ### Anything Else?
   
   Conditions, each verified by removing it:
   
     1. Java 8. Not reproducible on Java 21, including at 8 instances and 4x 
the payload.
     2. More than one Fory instance constructed in the JVM.
     3. An earlier serialization large enough to trigger JIT codegen. Built-in 
types alone never
        trigger it. A flat HashMap<Integer, UserType> of 6000 entries does NOT 
reproduce; several
        distinct generic shapes (Map<Integer,.>, Map<Long,.>, Set<Long>) do. It 
is not a simple
        size threshold — the same shape reproduces at 2000 entries per field 
but not at 10000.
     4. withRefTracking(true).
   
   The failure rate tracks how many builder methods are called. With 
withLanguage +
   requireClassRegistration(false) + withRefTracking(true) alone it reproduces 
intermittently;
   adding further builder calls raises the rate (8 runs each, Java 8; reproduce 
each row with the
   third arg, e.g. `... ForyMultiInstanceRepro 800 4 min`):
   
     builder config                                         arg        fail rate
     minimal (above)                                        min        2/8
     + withRefCopy(true)                                    copy       2/8
     + serializeEnumByName(true)                            enum       6/8
     + withNumberCompressed(false)                          num        7/8
     + withRefCopy(true) + withNumberCompressed(false)      copy+num   8/8
   
   serializeEnumByName(true) raises the rate although the payload contains no 
enums, and
   withRefCopy(true) affects only copy(), which is never called here. That 
suggests the trigger is
   sensitive to the number of action-recording builder methods replayed in 
ForyBuilder.factory(),
   rather than to any single option's semantics.
   
   withCodegen(false) and withAsyncCompilation(true) each reduce the rate 
without eliminating it,
   so neither is a workaround.
   
   Ruled out:
   
     - A shared SharedRegistry instance. Fory.<init>(builder, classLoader, 
sharedRegistry) does
       new SharedRegistry() when the argument is null, so separate instances do 
not share one.
     - The isLatin/ASCII range gap. StringEncodingUtils.isLatin(char[]) accepts 
chars <= 255 while
       the LOWER_SPECIAL encoders reject > 127, but encodeBinary(String, 
Encoding[]) correctly
       falls back to UTF-8 — verified with "café", "aÿ", "aĀ", "a中" on both 
JDKs.
       The gap applies only to the forced-encoding overload, which is what this 
path uses.
     - The multi-release jar. PlatformStringUtils and MemoryBuffer are 
overridden only under
       META-INF/versions/25/, so Java 8 and Java 21 both load the base classes.
   
   Possibly related:
   
     - #3828 — deserialization depending on Fory instance state (different 
symptom, same theme of
       cross-instance coupling).
     - #3546 — introduced caching of serializers and TypeInfo in SharedRegistry.
     - #2070 — a prior Java 8 vs 8+ divergence in the same internal 
registration path.
   
   Suggested hardening, independent of root cause:
   MetaStringEncoder.encodeBinary(String, Encoding) throws when the forced 
encoding cannot
   represent the string, while the Encoding[] overload falls back to UTF-8. 
Making the
   forced-encoding path fall back the same way would downgrade this from an 
error that permanently
   prevents Fory construction in the JVM to correct (if slightly larger) output.
   
   
   ### Are you willing to submit a PR?
   
   - [ ] I'm willing to submit a PR!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to