JDK-8033735 : make Throwable.backtrace visible to Class.getDeclaredField again
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-02-06
  • Updated: 2018-11-21
  • Resolved: 2016-04-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b116Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Currently Throwable.backtrace is treated by Class.getDeclaredField like an injected field; it is not reported back to the caller.  The reason it is hidden is because a crash that was reported (JDK-4496456) when a user tries to get the contents of the backtrace Object array.

Without knowing the history here JDK-4496456 was very likely because of the specific representation behind Throwable.backtrace back then.  This changed.  The Object[] looks now like:

Object[] backtrace = { short[] method_ids, int[] bcis, Object[] mirrors };

and it's perfectly sane to do:

        // Retrieve the class of throwable.backtrace[0][0].
        Class class2 = ((Object[]) ((Object[]) backtrace)[0])[0].getClass();

(although it will bail out with a ClassCastException).

To make sure this doesn't break again we could take the test case of JDK-4496456 and make a regression test.
Comments
I would have argued for switching to the registerFieldsToFilter mechanism. There is really no reason to expose this field to any user code, and now that you have I would not be surprised if its appearance causes something to break.
18-04-2016

Yes, this isn't recommended even though it's in the test. We are free to change this at any time and anyone with this sort of code will get a ClassCastException.
08-04-2016

I agree the VM filtering code is ugly that should be removed. If a field needs be filtered with a good justification (in general should not filtered), sun.reflect.Reflection::registerFieldsToFilter is the mechanism. I have no objection to Throwable.class.getDeclaredField to find backtrace field. However I strongly recommend not doing this mentioned in the description: Class class2 = ((Object[]) ((Object[]) backtrace)[0])[0].getClass(); as the format is opaque.
08-04-2016

Sure. All I care about is for the VM filtering code to go away. Should we move this bug to hotspot/runtime?
08-04-2016

I agree that the filtering code should go away. I was wondering why it was there but didn't get a chance to read the bug. I don't think the backtrace field should be changed to Object[] however. The format of the backtrace field should be completely opaque to the Java code, as Mandy and David said.
08-04-2016

No, this is completely unrelated. The filtering code in the VM is just ugly and was added because of a crash. I am arguing since the VM does not crash anymore the filtering code should go away.
07-04-2016

Yes, it's done in the VM. Look at the attached patch.
07-04-2016

Why do you need to access this private field? I would consider the backtrace like a VM injected field and the content is written by the VM. it's an opaque object whose format is subject to change any time. BTW I don't see sun.reflect.Reflection::registerFIeldsToFilter on Throwable::backtrace field is called. Where does it get filtered? Done in the VM?
07-04-2016

Does anyone have an opinion?
07-04-2016

Moving to core-libs to get more input.
16-05-2014

[~alanb], any thoughts?
06-05-2014

Once this is exposed and people start to use it then removing it later will be a problem. I see no reason to expose it in the first place. But again take this up with core-libs folk.
13-02-2014

Since backtrace is a private field I don't think we are guaranteeing anything. Except maybe to our own core library people. Now that HSX is dead HotSpot and JDK changes go in tandem and if we are going to change the internal stack trace representation we can also change this field. Personally I don't like the pattern of injected fields; they are more pain than actually gain.
13-02-2014

I don't think this is something that needs changing. While it may be that the backtrace[] elements are now all valid java objects, if we expose this we are guaranteeing they will always be so. That seems unnecessarily restrictive for the VM. This is a VM internal data structure used to optimize StackTrace creation, it isn't meant for direct access. If not for performance this could be a true injected field only accessible via the VM. That said this is really a core-libs matter, in particular Joe Darcy may have a strong view.
06-02-2014

[~dholmes], I definitely would like your input here.
06-02-2014

Additionally to the suggested JVM fix I'd change the type of Throwable.backtrace to Object[]: diff -r f2195a4340b8 src/share/classes/java/lang/Throwable.java --- a/src/share/classes/java/lang/Throwable.java Thu Jan 23 15:17:36 2014 +0100 +++ b/src/share/classes/java/lang/Throwable.java Wed Feb 05 17:45:59 2014 -0800 @@ -118,7 +118,7 @@ public class Throwable implements Serial /** * Native code saves some indication of the stack backtrace in this slot. */ - private transient Object backtrace; + private transient Object[] backtrace; /** * Specific details about the Throwable. For example, for
06-02-2014