Slow performance of StackWalker.getCallerClass() vs Reflection.getCallerClass()
Kasper Nielsen
kasperni at gmail.com
Wed Jul 3 04:54:46 UTC 2019
On Tue, 2 Jul 2019 at 18:50, Mandy Chung <mandy.chung at oracle.com> wrote:
>
> I'm not getting how getCallerClass is used and related to access check.
> Can you elaborate?
Caller sensitive methods are viral, in the sense that if you invoke a caller
sensitive method in the JDK, as a library on behalf of a client (without
having a lookup object). You need to perform the same access checks as the JDK
does. That is, checking that the client that calls you - the library - has the
right access rights. The caller sensitive methods in the JDK cannot do this,
because there is no way for them to see that the library is merely a proxy
acting on behalf of a client.
Consider a very simple serialization library with one method
String serializeToString(Object o) // prints out the value of every field
with an implementation in a module called SER. And two modules M1, M2 that uses
SER (For example, via a ServiceLoader). Both M1 and M2 are open to SER in order
for the serializer to serialize the objects in each of the two modules.
However, M1 and M2 are not open towards each other. So it is not the intention
that, for example, some code from M1 can call it with objects from M2 and have
them serialized or vice versa. However, this is entire possible unless
serializeToString() performs access checks on the caller. All M1 has to do is
get a hold of an object from M2 and then call serializeToString() with it.
There is no way the jdk can check this, it just sees an object from M2 which
is open to SER. It has no idea it is actually M1 trying to serialize it. So
the only way for this to work as intended is for serializeToString to check
that the caller matches the object. And unless you pass around Lookup objects
the only way you can do it, is similar to how the jdk does it; by looking at the
calling class. Reflection::getCallerClass is not available outside of the JDK,
so StackWalker is the only way to do this.
I've put up an example at https://github.com/kaspernielsen/modulestest.
Calling M2Use.main will serialize an object from M1 even though it M1 is
not open to M2.
As noted in another thread this gets further complicated because all the access
control code is buried in internal jdk classes. In this example you more or less
have to reimplement AccessibleObject.checkCanSetAccessible yourself.
In the end I don't think it is realistic to expect library developers to get
this right.
/Kasper
More information about the core-libs-dev
mailing list