Skip to content

Remove virtual field interfaces from reflection results - #4722

Merged
trask merged 2 commits into
open-telemetry:mainfrom
laurit:virtual-field-interfaces
Nov 29, 2021
Merged

Remove virtual field interfaces from reflection results#4722
trask merged 2 commits into
open-telemetry:mainfrom
laurit:virtual-field-interfaces

Conversation

@laurit

@laurit laurit commented Nov 26, 2021

Copy link
Copy Markdown
Contributor

Resolves #4370
I initially planned to use asm SerialVersionUIDAdder to add serialVersionUID field to serializable classes that don't declare it. This is needed to make sure that instrumented version of class has the same serialVersionUID as uninstrumented version. This approach failed with one of spring-batch tests because inside spring there is code that copies instances of an internal spring class via reflection and fails because it can't write to serialVersionUID which is a static final field. We can't use the same reflection filtering code as we use for fields & methods added by virtual field implementetion because that filtering completely removes these members from reflection results. For serialVersionUID we'd need it to be visible from getDeclaredField, so that ObjectStreamClass can read it, and hidden from getDeclaredFields, so that code that isn't explicitly looking for it wouldn't stumble upon it. Instead of attempting to remove serialVersionUID from getDeclaredFields I chose to remove interfaces added by virtual field implementation from the result of getInterfaces. This makes the default serialVersionUID computation algorithm return the correct result on instrumented classes and there is no need to precompute serialVersionUID for them.

@iNikem iNikem left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope you know what you are doing :D Instrumenting java.lang.Class seems scary

@trask

trask commented Nov 28, 2021

Copy link
Copy Markdown
Member

@laurit do you think we could get rid of these interfaces and use method handles to access the generated methods?

@laurit

laurit commented Nov 29, 2021

Copy link
Copy Markdown
Contributor Author

@trask Firstly we would need to figure out a new way to detect whether virtual fields have been added to a class which is currently handled by testing for VirtualFieldInstalledMarker interface or virtual field accessor interface. This could be implemented using a map with class name+class loader as key, but as the whole point of virtual fields is to avoid using maps we'd probably need to come up with something else. If we somehow end up using method handles then one thing to consider is that we can't always initialize them in static initializer because presence of <clinit> method also changes the default serial version uid.

@@ -36,6 +38,7 @@ public static Method[] filterMethods(Class<?> containingClass, Method[] methods)
return methods;
} else if (containingClass.isInterface()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, I'll open an issue to try this 👍

@trask trask left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presence of <clinit> method also changes the default serial version uid.

😭

@@ -36,6 +38,7 @@ public static Method[] filterMethods(Class<?> containingClass, Method[] methods)
return methods;
} else if (containingClass.isInterface()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, I'll open an issue to try this 👍

@trask
trask merged commit 92f83f1 into open-telemetry:main Nov 29, 2021
@laurit
laurit deleted the virtual-field-interfaces branch November 29, 2021 20:10
RashmiRam pushed a commit to RashmiRam/opentelemetry-auto-instr-java that referenced this pull request May 23, 2022
…ry#4722)

* Remove virtual field interfaces from reflection results

* fix java8 and openj9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compute serialVersionUID for Serializable classes that don't have one and use VirtualField

4 participants