On 9/4/2013 6:02 PM, David M. Lloyd wrote:
This seems reasonable on the surface but falls over once you capture the caller for more than one purpose. For example, say a logging framework captures the caller for the purpose of supplementing log information. But you call this logging framework from another framework which uses caller information for another purpose, for example locating resources. The intent here might be to show information from the second framework in the log, however with one universal @CallerSensitive annotation you cannot distinguish which "capture" you want to grab - the second framework, or the caller who called the second framework. However by traversing the stack to a fixed depth, you can do so very definitively (as long as you always know that your internal code does *not* directly call the sensitive method - an easy thing to design for in most frameworks).
It would need to detect if the intermediate frames don't call any "sensitive" method.
@sun.reflect.CallerSensitive is primarily defined for the security issue and specifically for JEP 176. As you said, the current form of @CS doesn't satisfy other purposes.
In fact you can usually traverse the stack to a fixed depth for this kind of thing, with one key exception that comes up in log frameworks. When you have one log API which forwards to another, you want to capture the "first" caller of any log API. Pursuant to this, most log frameworks have log method variants which accept the fully-qualified class name of that first logger. The moral equivalent to this scenario would likely be to provide an API variant which accepts a Class or ClassLoader (depending on the usage) and a variant which does not and uses a fixed-depth "reach" into the stack instead. This IMO blows a hole in the whole idea of a single *public* @CS annotation, and in fact in public framework code, a depth indicator seems to be adequate and more or less problem-free for any purpose I've run across.
I'm not sure if we can be very certainabout the depth in a runtime environment (non-debugging) unless it requires all VM implementation to support a reliable way to return a frame at a given depth.
The stack trace is not guaranteed to contain all stack frames. E.g. in the spec of Throwable.getStackTrace():
Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method. Mandy
