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

JacksonBlackbirdAccess Class access exception with Groovy Script Serialization Using BlackbirdModule #285

Open
apoorvam opened this issue Feb 17, 2025 · 4 comments
Labels
blackbird Issue related to Blackbird module

Comments

@apoorvam
Copy link

apoorvam commented Feb 17, 2025

I'm encountering an issue when attempting to use the BlackbirdModule in a Spring Boot 3.2 application with Groovy scripting. The goal is to serialize a Groovy object into JSON using the Jackson ObjectMapper with the BlackbirdModule. However, the test case below fails with an exception during the serialization of a Groovy object.

 @Test
    void testGroovySerializationWithBlackbird() throws Exception {
        // Define a Groovy script as a String
        String script = """
                    import com.fasterxml.jackson.databind.ObjectMapper
                    import com.fasterxml.jackson.module.blackbird.BlackbirdModule

                    class Person {
                        String name
                        int age
                    }

                    def mapper = new ObjectMapper()
                    mapper.registerModule(new BlackbirdModule())

                    def person = new Person(name: "Groovy User", age: 35)
                    def json = mapper.writeValueAsString(person)

                    return json // Returning the JSON string
                """;

        // Execute the Groovy script
        GroovyShell shell = new GroovyShell();
        Object result = shell.evaluate(script);

        assertNotNull(result);
    }

Exception:

java.lang.ClassFormatError: Illegal class name "/$$JacksonBlackbirdAccess" in class file /$$JacksonBlackbirdAccess
	at java.base/java.lang.ClassLoader.defineClass0(Native Method)
	at java.base/java.lang.System$2.defineClass(System.java:2394)
	at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2505)
	at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2480)
	at java.base/java.lang.invoke.MethodHandles$Lookup.defineClass(MethodHandles.java:1865)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.accessClassIn(CrossLoaderAccess.java:131)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.grantAccess(CrossLoaderAccess.java:94)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.apply(CrossLoaderAccess.java:83)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.apply(CrossLoaderAccess.java:11)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.createProperty(BBSerializerModifier.java:109)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.lambda$findProperties$0(BBSerializerModifier.java:67)
	at com.fasterxml.jackson.module.blackbird.util.Unchecked.lambda$runnable$0(Unchecked.java:31)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.findProperties(BBSerializerModifier.java:68)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.changeProperties(BBSerializerModifier.java:52)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanOrAddOnSerializer(BeanSerializerFactory.java:415)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanOrAddOnSerializer(BeanSerializerFactory.java:295)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:240)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:174)
	at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1503)
	at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1451)
	at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:556)
	at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:834)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:307)
	at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4719)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3964)
	at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)
	at Script1.run(Script1.groovy:13)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:460)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:495)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:469)
	at JacksonBlackbirdTest.testGroovySerializationWithBlackbird(JacksonBlackbirdTest.java:100)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

I am using jackson-bom version 2.15.4 and Groovy 4.0.17 that's default with Spring Boot 3.2. Any suggestions? Removing Blackbird module in above test passes, works even with afterburner module. Just not with blackbird module.

@apoorvam
Copy link
Author

Hi, would like to know if there are any workarounds for this. Any suggestions?

@cowtowncoder cowtowncoder added the blackbird Issue related to Blackbird module label Feb 25, 2025
@cowtowncoder
Copy link
Member

My main suggestion would be to try a more recent version -- ideally 2.18.2 -- of Jackson components.
There are occasionally fixes to Blackbird and this would rule out possibility later version works better.

Otherwise I suspect Groovy-generated class has name that somehow Blackbird has issues with. Perhaps it is in the "default package" (i.e. one without name) and BB does not handle that case well.

@stevenschlansker WDYT?

@apoorvam
Copy link
Author

apoorvam commented Feb 25, 2025

I tried with 2.18.2 and see the same error unfortunately.

java.lang.ClassFormatError: Illegal class name "/$$JacksonBlackbirdAccess" in class file /$$JacksonBlackbirdAccess
	at java.base/java.lang.ClassLoader.defineClass0(Native Method)
	at java.base/java.lang.System$2.defineClass(System.java:2394)
	at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2505)
	at java.base/java.lang.invoke.MethodHandles$Lookup$ClassDefiner.defineClass(MethodHandles.java:2480)
	at java.base/java.lang.invoke.MethodHandles$Lookup.defineClass(MethodHandles.java:1865)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.accessClassIn(CrossLoaderAccess.java:131)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.grantAccess(CrossLoaderAccess.java:94)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.apply(CrossLoaderAccess.java:83)
	at com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.apply(CrossLoaderAccess.java:11)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.createProperty(BBSerializerModifier.java:111)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.lambda$findProperties$0(BBSerializerModifier.java:69)
	at com.fasterxml.jackson.module.blackbird.util.Unchecked.lambda$runnable$0(Unchecked.java:31)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.findProperties(BBSerializerModifier.java:70)
	at com.fasterxml.jackson.module.blackbird.ser.BBSerializerModifier.changeProperties(BBSerializerModifier.java:54)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanOrAddOnSerializer(BeanSerializerFactory.java:415)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanOrAddOnSerializer(BeanSerializerFactory.java:295)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:240)
	at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:174)
	at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1523)
	at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1471)
	at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:578)
	at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:856)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:330)
	at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4811)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:4052)
	at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)
	at Script1.run(Script1.groovy:13)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:460)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:495)
	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:469)

@cowtowncoder How can I inspect this Groovy generated class to root cause this?

@cowtowncoder
Copy link
Member

To be honest, I don't know. Maybe debugging on com.fasterxml.jackson.module.blackbird.CrossLoaderAccess.accessClassIn would show name of dynamic class being generated?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blackbird Issue related to Blackbird module
Projects
None yet
Development

No branches or pull requests

2 participants