Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 22 - error serialization and deserialization BigDecimal #80

Open
PRIESt512 opened this issue Mar 24, 2024 · 2 comments
Open

Java 22 - error serialization and deserialization BigDecimal #80

PRIESt512 opened this issue Mar 24, 2024 · 2 comments
Assignees

Comments

@PRIESt512
Copy link

Example:
var byt = one.nio.serial.Serializer.persist(BigDecimal.ZERO);
Error:

Exception in thread "main" java.lang.VerifyError: Bad invokespecial instruction: current class isn't assignable to reference class.
Exception Details:
  Location:
    sun/reflect/Delegate0_BigDecimal.write(Ljava/lang/Object;Lone/nio/serial/DataStream;)V @9: invokespecial
  Reason:
    Error exists in the bytecode
  Bytecode:
    0000000: 2bc0 0015 4c2b b200 1bb7 001f 2c2b b400
    0000010: 23b6 0031 2c2b b400 34b6 0038 b1       

	at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3572)
	at java.base/java.lang.Class.getConstructor0(Class.java:3777)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2955)
	at one.nio.serial.gen.DelegateGenerator.instantiate(DelegateGenerator.java:108)
	at one.nio.serial.GeneratedSerializer.<init>(GeneratedSerializer.java:57)
	at one.nio.serial.Repository.generateFor(Repository.java:379)
	at one.nio.serial.Repository.get(Repository.java:182)
	at one.nio.serial.PersistStream.writeObject(PersistStream.java:52)
	at one.nio.serial.Serializer.persist(Serializer.java:140)

Version one-nio: 1.7.1

@PRIESt512
Copy link
Author

Hi, I did some digging in the code and came up with the following results for now. Bytecode generation for BigDecimal processing in one place is created incorrectly. This error occurs in two methods - one.nio.serial.gen.DelegateGenerator#generateCalcSize and one.nio.serial.gen.DelegateGenerator#generateWrite.
In the one.nio.serial.gen.DelegateGenerator#emitWriteObject method there is a call one.nio.gen.BytecodeGenerator#emitInvoke(org.objectweb.asm.MethodVisitor, java.lang.invoke.MethodHandleInfo):

        int opcode;
        if ((m.getModifiers() & Modifier.STATIC) != 0) {
            opcode = INVOKESTATIC;
        } else if ((m.getModifiers() & Modifier.PRIVATE) != 0) {
            opcode = INVOKESPECIAL;
        } else if (m.getDeclaringClass().isInterface()) {
            opcode = INVOKEINTERFACE;
        } else {
            opcode = INVOKEVIRTUAL;
        }

And to call java.math.BigDecimal#writeObject, invokespecial is used.
Trying to replace with invokevirtual results in a different error:

Exception in thread "main" java.lang.IllegalAccessError: class sun.reflect.Delegate0_BigDecimal tried to access private method 'void java.math.BigDecimal.writeObject(java.io.ObjectOutputStream)' (sun.reflect.Delegate0_BigDecimal is in unnamed module of loader one.nio.gen.BytecodeGenerator @6bc168e5; java.math.BigDecimal is in module java.base of loader 'bootstrap')
	at sun.reflect.Delegate0_BigDecimal.write(Unknown Source)
	at one.nio.serial.GeneratedSerializer.write(GeneratedSerializer.java:121)
	at one.nio.serial.PersistStream.writeObject(PersistStream.java:60)
	at one.nio.serial.Serializer.persist(Serializer.java:140)

P.S. I commented on the following calls:

//        generateRead(cv, cls, fds, defaultFields, className);
//        generateSkip(cv, fds);
//        generateToJson(cv, cls, fds);
//        generateFromJson(cv, cls, fds, defaultFields, className);

There were other errors with them:

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    sun/reflect/Delegate0_BigDecimal.read(Lone/nio/serial/DataStream;)Ljava/lang/Object; @5: invokevirtual
  Reason:
    Type uninitialized 1 (current frame, stack[2]) is not assignable to 'java/lang/Object'
  Current Frame:
    bci: @5
    flags: { }
    locals: { 'sun/reflect/Delegate0_BigDecimal', 'one/nio/serial/DataStream' }
    stack: { uninitialized 1, 'one/nio/serial/DataStream', uninitialized 1 }
  Bytecode:
    0000000: 2bbb 0015 5ab6 003f 592b b600 43c0 0045
    0000010: 1400 46b8 004d 592b b600 5114 0052 b800
    0000020: 5759 59bb 0059 5a5f 2ab4 000f b700 5cb6
    0000030: 005f b0                                

	at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3572)
	at java.base/java.lang.Class.getConstructor0(Class.java:3777)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2955)
	at one.nio.serial.gen.DelegateGenerator.instantiate(DelegateGenerator.java:107)
	at one.nio.serial.GeneratedSerializer.<init>(GeneratedSerializer.java:57)
	at one.nio.serial.Repository.generateFor(Repository.java:379)
	at one.nio.serial.Repository.get(Repository.java:182)
	at one.nio.serial.PersistStream.writeObject(PersistStream.java:52)
	at one.nio.serial.Serializer.persist(Serializer.java:140)

@apangin
Copy link
Member

apangin commented Aug 21, 2024

The problem is not specific to BigDecimal.
one-nio serialization stopped working in JDK 22 and beyond because of JDK-8305104.

@lehvolk lehvolk self-assigned this Oct 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants