On 11/15/2015 05:53 PM, Timo Kinnunen wrote:
To be pedantic, there is always a caller, but not every caller is associated 
with a Java Class.

StackWalker::getCallerClass can be thought as a convenience method for 
something like:
        Class<?> callingMe = StackWalker.getCaller().getAsJavaClass();

 From this view-point we can determine that
• getCaller() will never return null as there is always a caller.
• getAsJavaClass() cannot always return a Class instance as the caller might be 
the OS itself or a native code frame.
• getCaller() will not return the current frame as the caller of the current 
frame because that’s nonsensical!
• Also, getAsJavaClass() will not return a Java Class from some other caller as 
that would violate its API contract.
• getAsJavaClass() will not return the current frame’s Class as the caller’s 
Class unless such a recursive call is actually in progress!

We can guess that the client using these methods should have some idea if it’s 
expected its caller is a Java Class or not. We also know the association 
between a caller and a Java Class (if any) won’t change unexpectedly or 
otherwise have some uncertainty. Together these give the following API for 
getCaller() and getAsJavaClass():

getCaller() always succeeds and returns non-null. The result is not guaranteed 
to contain information useful to clients. It returns the same caller regardless 
of who the callers of the caller are.
getAsJavaClass() doesn’t always succeed, and when it does is dependent on local 
information only. When it doesn’t, it throws an exception to signal that the 
association to a Class that the client expected to find doesn’t exists. The 
exception is not a checked exception because the association between a caller 
and a Class is not inherently unreliable.

The same reasoning applies to StackWalker::getCallerClass and further suggests 
StackWalker::getCaller should be available for clients as well.

But what would StackWalker::getCaller actually return? If it is an object that contains just getAsJavaClas() method, then it is a useless indirection (similar to Optional<Class<?>>).

Since the situation that a "caller-sensitive" method is not called by a Java method is really just a theoretical issue and even then it is an abuse made by the caller of a caller-sensitive method, I would just make getCallerClass() throw an exception in such situations.

Regards, Peter





Sent from Mail for Windows 10



From: David M. Lloyd
Sent: Saturday, November 14, 2015 16:02
To: core-libs-dev@openjdk.java.net
Subject: Re: Proposed API for JEP 259: Stack-Walking API


On 11/13/2015 06:07 PM, Brian Goetz wrote:
I considered Optional<Class<?>>. I believe it is rare to have a JNI
attached thread calling StackWalker::getCallerClass from native.  Most
common cases will find a caller class.   Returning an Optional will
force most common uses to handle the case if it’s absent.  It’s a
tradeoff that I think it’s better to return Thread.class for the JNI
attached thread calling getCallerClass in native which would rarely
happen.
+1 on returning Thread.class in these cases.  Its a pragmatic compromise.
If you must return something non-null, maybe it'd be better to define a
class just for that purpose, e.g.:

public final class StackWalker {

      ...

      public static final class NoCaller {
          private NoCaller() {}
      }
}

...and use NoCaller.class as your caller when there is none.  Bonus
points if you can attach a protection domain with no permissions to that
class.


Reply via email to