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

Skip serialization of groovy.lang.MetaClass values to avoid StackOverflowError #93

Closed
chashnikov opened this issue Jan 20, 2022 · 8 comments
Labels
Milestone

Comments

@chashnikov
Copy link

chashnikov commented Jan 20, 2022

Try serializing empty Groovy class using Groovy 3.0.9 and jackson-jr-objects:2.13.1:

import com.fasterxml.jackson.jr.ob.JSON
import groovy.transform.CompileStatic

class MyBean {}

@CompileStatic
class JsonTest {
    static void main(String[] args) {
        println JSON.std.asString(new MyBean())
    }
}

It'll fail with StackOverflowError:

	at com.fasterxml.jackson.jr.ob.impl.JSONWriter.writeBeanValue(JSONWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.BeanWriter.writeValue(BeanWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.JSONWriter._writeValue(JSONWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.JSONWriter.writeBeanValue(JSONWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.BeanWriter.writeValue(BeanWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.JSONWriter._writeValue(JSONWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.JSONWriter.writeBeanValue(JSONWriter.java)
	at com.fasterxml.jackson.jr.ob.impl.BeanWriter.writeValue(BeanWriter.java)

This happens because every class file generated from Groovy class contains getMetaClass method, which contains data with meta-information with cyclic references inside. The method is marked with @java.beans.Transient annotation, so if serialization automatically skips such properties, the problem will be solved.

@cowtowncoder
Copy link
Member

I think it is possible for users to implement something like this, similar to jr-annotation-support.

Now, this could make useful addition to jr-annotation-support itself, but there is one practical problem: annotation was added in JDK 7, and jackson-jr only requires JDK 6 as of Jackson 2.13. We could consider increasing baseline to JDK 8 in which case it'd be possible to add support.

If anyone wanted to provide a PR for addition here, I'd be happy to help to see if JDK baseline can be improved.

@chashnikov
Copy link
Author

annotation was added in JDK 7, and jackson-jr only requires JDK 6 as of Jackson 2.13

It's possible to check if an element is annotated with Transient without referencing the class, you may just iterate over Method::getDeclaredAnnotations and compare annotation.annotationType().getName() with "java.beans.Transient" string.

@cowtowncoder
Copy link
Member

cowtowncoder commented Jan 27, 2022

True, there are ways around that. And although it's bit brittle (relying on names) it might be fine.
The other possible challenge is testing: is it possible for Maven project to require Java 8 for tests, but not for main code?
If so, that sounds good.

Oh. However... there is a good reason for NOT adding dependency to that class at all: it will bring big non-core Beans module for JDK 9+. So maybe by-name check is the proper way to go.

So, I'd be open for addition if anyone has time to work on PR.

I would also suggest adding a feature to enable/disable recognition of this annotation: I fully expect someone somewhere to NOT want ignoral. This based on adding similar features in the past.

@cowtowncoder cowtowncoder removed the 2.14 label Feb 16, 2024
@cowtowncoder
Copy link
Member

Quick note: JDK 8 has been baseline since 2.14 (as per #95) so this could just be added now.

@cowtowncoder
Copy link
Member

I think this would be good thing to have PR for; marking as such.

@cowtowncoder cowtowncoder added pr-welcome Issue for which progress most likely if someone submits a Pull Request good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project labels Feb 16, 2024
@Shounaks
Copy link
Contributor

Okay, this might sound a bad programming practice, but I noticed skipping over groovy MetaClassImpl to be a better alternative than checking for annotations. (I tried first & didnt work).
image
Adding a simple line of code can fix this.

currType.getName().equals("groovy.lang.MetaClassImpl")

but since this is not optimal solution , i would like to hear your thoughts @cowtowncoder ? Do we really require groovy class metadata?

@cowtowncoder
Copy link
Member

I think core jackson-databind does something like this to automatically ignore this problematic type (in... src/main/java/com/fasterxml/jackson/databind/util/BeanUtil.java I think).
So while it's not super-clean approach, I think in this particular case it makes lots of sense.

So I think a PR for such patch would make sense.

One thing that'd be great would be unit test showing this in action, but not sure how easy that'd be to do.

cowtowncoder added a commit to Shounaks/jackson-jr that referenced this issue Feb 21, 2024
cowtowncoder added a commit to Shounaks/jackson-jr that referenced this issue Feb 21, 2024
@cowtowncoder
Copy link
Member

@chashnikov Our attempts to reproduce the issue with 2.17 code is not successful (see #118). Not sure why; not sure if @CompileStatic is truly required, but also not able to use that (org.codehaus.gmaven:gmaven-plugin:1.5: fails to compile things)

So some help would be needed to reproduce the issue: fix itself should be relatively easy after that.

@cowtowncoder cowtowncoder changed the title Automatically skip getters/setters marked with @Transient annotation Skip serialization of groovy.lang.MetaClass values to avoid StackOverflowError Feb 21, 2024
@cowtowncoder cowtowncoder removed enhancement pr-welcome Issue for which progress most likely if someone submits a Pull Request good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project labels Feb 21, 2024
@cowtowncoder cowtowncoder added this to the 2.17.0 milestone Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants