Request for review (#4) 7174978: NPG: Fix bactrace builder for class redefinition
coleen.phillimore at oracle.com
Mon Jan 14 18:36:21 PST 2013
Summary: Remove Method* from backtrace but save version so redefine
classes doesn't give inaccurate line numbers. Removed old Merlin API
with duplicate code.
Sorry, this is so long but I want to explain this change properly.
When exceptions are thrown, the VM saves a backtrace for each which may
or may not be printed or saved for later. For speed, the information
that the VM saves are arrays 32 of Method* and bci. For permgen
elimination we added an array of mirrors (instances of java_lang_Class),
so that the class loader owning the Method* pointer doesn't get unloaded
The problem with redefine classes is that the method can be redefined
and the Method* pointer can be deallocated even if the class loader
owning the Method* is kept alive. Printing or touching the backtrace
later will crash the VM.
This is my 4th attempt at fixing this problem. The first that was
reviewed, saved a side structure for each backtrace created so that we
can walk the Method* pointers and keep them from being deallocated.
This change had an unfortunate side structure to manage, and had also a
6.1% slowdown in javac. The second attempt was to predigest the
Method* into the data needed for java_lang_StackTraceElement into
method_name, class_name, file_name, and line_number, so that the Method*
doesn't need to be saved. This had a 18% slowdown in javac.
The 3rd attempt is to look for a way to have GC handle backtraces and
mark methods as on_stack but adding a InstanceThrowableKlass and
determining which closures needed special actions for the array of
Method* pointers is a lot of additional special case code to the garbage
collectors. It's unclear how this would work actually, but we might
have to revisit this idea for java_lang_invoke_MemberName.
The 4th attempt is to save the method_idnum, bci, version_number, and
mirror. From the method_idnum, we can get the Method*. The version
number is updated for redefine classes. There was an unused field that
I repurposed. If the method's version doesn't match the backtrace, we
do not return the source_file and line_number from the Method* because
it's changed. You get a backtrace of the form:
java.lang.RuntimeException: Test exception
at RedefineMethodInBacktraceTarget.methodToRedefine(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
This fix for the Method* crash does not add to the footprint of the
backtraces (idnum is short and bci and version number is packed into an
int). It does not degrade performance of javac (or refworkload). The
cost is to not support getting a source file and line number from a
method that was redefined after being saved in a backtrace. Note that
this change does not return the wrong information. A CR can be filed
for somebody to someday lift this restriction if someday we don't care
about performance or a new solution is found.
This might be hard to review as a diff because I refactored duplicated code.
The webrev: http://cr.openjdk.java.net/~coleenp/7174978_5/
Bug link: http://bugs.sun.com/view_bug.do?bug_id=7174978
Tested with NSK quick testlist, runThese jck tests, JPRT, refworkload.
More information about the hotspot-runtime-dev