Re: Classes on the stack trace (was: getElementClass/StackTraceElement, was: @CallerSensitive public API, was: sun.reflect.Reflection.getCallerClass)
jhuxhorn at googlemail.com
Tue Jul 30 12:01:00 UTC 2013
This whole issue started with the "fix" of http://bugs.sun.com/view_bug.do?bug_id=8016814 because, obviously, throwing an UnsupportedOperationException is a straightforward and reasonable way of fixing an off-by-one problem with the description "returns the wrong stack frame" (see http://mail.openjdk.java.net/pipermail/jdk7u-dev/2013-June/006791.html).
Bonus points for doing this instead of just applying the "1-line fix" in the comments of that bug report. I'm pretty sure that this exception wasn't the kind of fix the reporter of the bug was looking for. (Yes, I know. The 1-line fix was applied and is executing if the JVM parameter is set - but this is not my point.)
Ironically, the comment on the "fix" regarded a sudden, unexpected RuntimeException in an unknown amount of third-party code as "Low risk.".
This is justified by http://bugs.sun.com/view_bug.do?bug_id=8014925 (created on 2013-05-20 - which is just the blink of an eye in Java time. To put it into perspective: we missed the tenth birthday of http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4851444 which requested this functionality in a proper public API) which contains the following paragraph:
> The following describes the transition plan to allow customers to migrate their applications away from this private API:
> 1. Disable sun.reflect.Reflection.getCallerClass(int) in 7u40 and provide a flag to re-enable it
> 2. Determine how this private API is being used and the use cases
> 3. Remove this private API if there is no valid use case or there is a proper replacement for it. Allow at least 2 CPU releases to allow customers to make appropriate change. So the earliest for the removal is 7u55. If there are valid use cases but no proper replacement, we may keep this private API in jdk7u for longer.
With regards to 3., I think we were able to give examples of "valid use cases" for this API.
If the only alternatives available are either slow and fragile (100x slower, achieved by extending SecurityManager for the sake of calling the protected getClassContext() method, will break if the RuntimePermission "createSecurityManager" is not granted by a possibly installed SecurityManager) or even slower (450x slower, using Throwable) then this is a showstopper, especially if the code is executed literally millions of times, as is the case with logging calls.
Yes. It sucks that a private API call is necessary. Yep, one should not depend on such a private API. But the RFE to rectify this has been idling for more than ten years and the performance impact of *not* using it is substantial.
The j7u40 change will result in lots of applications simply going BOOM or acting weird after updating which in turn will slow the adoption of Java updates. And that isn't a good idea at all with regards to security fixes. It will likely also prevent reasonable adoption rates for Java 8. Why should I choose a new Java version if it results in a significantly slower overall speed of my applications? If all third-party libraries using the API have been updated so that the application will work at all.
There's really only one rational way to handle this situation:
- Remove the UnsupportedOperationException from j7u40 und higher Java 7 versions.
- Restore sun.reflect.Reflection in Java 8.
- Define a proper public API (TBD) with similar performance to the private API, as requested ten years ago, for Java 9. This functionality is available in .NET since 1.1, as previously mentioned.
Anything else will simply hurt the Java platform as a whole and reaffirm the "Java is slow" mantra. If keeping the "but this wasn't part of the public API so we did nothing wrong" stance is worth all of this then feel free to just ignore our objections.
Seriously, I fail to understand how something like this could have passed the QA. See http://code.ohloh.net/search?s=Reflection.getCallerClass for a rough estimate about the impact of this change. This is probably one of the most used private Java API calls, ever.
On 30. Juli 2013 at 06:59:53, Nick Williams (nicholas+openjdk at nicholaswilliams.net) wrote:
On Jul 29, 2013, at 11:59 PM, Joseph Darcy wrote:
> On 7/29/2013 9:31 PM, Alan Bateman wrote:
>> On 29/07/2013 19:17, David M. Lloyd wrote:
>>> Your phrasing makes me think I missed something: is the Reflection.getCallerClass() method being removed due to some technical issue that it can only be somehow emulated as a workaround? Or is it just a general cleanup effort?
>> The sun.reflect.Reflection.getCallerClass(int) method was removed as part of JEP 176 .
>>  http://openjdk.java.net/jeps/176
> And as a sun.* method, this was officially outside of the exported interface of the JDK and not something that should be expected to work if called from outside of the JDK.
As has been said many, many times in the last few days, we are all well aware of this. It doesn't make the problem any less disastrous for the community. This needs to be replaced with a public API.
More information about the core-libs-dev