RFR: 8302491: NoClassDefFoundError omits the original cause of an error [v2]
David Holmes
dholmes at openjdk.org
Wed Feb 15 03:16:48 UTC 2023
On Wed, 15 Feb 2023 02:39:24 GMT, Ilarion Nakonechnyy <inakonechnyy at openjdk.org> wrote:
>> The proposed approach added a new function for getting the cause of an exception -`java_lang_Throwable::get_cause_simple `, that gets called within `InstanceKlass::add_initialization_error` if an old one `java_lang_Throwable::get_cause_with_stack_trace` didn't succeed because of an exception during the VM call. The simple function doesn't call the VM for getting a stack trace but fills in any other information about an exception.
>>
>> Besides that, the discovering information about an exception was added to `ConstantPoolCacheEntry::save_and_throw_indy_exc` function.
>>
>> Jtreg for reproducing the issue also was added to the commit.
>> The commit was tested with tier1 tests.
>
> Ilarion Nakonechnyy has updated the pull request incrementally with two additional commits since the last revision:
>
> - Address review notes
> - Correct the jtreg test -
> check stacktrace only for NoClassDefFoundError
So if I understand correctly the scenario is:
1. During execution of clinit of class C a StackOverflowError is thrown.
2. The VM sees the exception and creates the NoClassDefFoundError for C
3. The VM calls `get_cause_with_stack_trace` to get the original SOE but that triggers a secondary SOE.
4. The VM ignores the secondary SOE and the NCDFE is created without a cause.
The fix is to retry step 3 avoiding the Java upcall and so avoiding a secondary SOE.
Is that right?
A few nits/suggestions below.
Thanks
src/hotspot/share/classfile/javaClasses.cpp line 2783:
> 2781: }
> 2782:
> 2783: Handle java_lang_Throwable::get_cause_simple(JavaThread* current, Handle throwable) {
How about `get_cause_without_stacktrace`?
The two methods should be able to share a lot of code rather than duplicating most of it.
src/hotspot/share/classfile/javaClasses.cpp line 2784:
> 2782:
> 2783: Handle java_lang_Throwable::get_cause_simple(JavaThread* current, Handle throwable) {
> 2784: // Same as get_cause_with_stack_trace, but without calling a JVM.
The comment at L2739:
// Call to JVM ...
is wrong as it is actually calling Java. Your comment should be more like:
// Similar to `get_cause_with_strace` but avoids the Java upcall to get the stacktrace, and
// so avoids triggering further exceptions.
src/hotspot/share/classfile/javaClasses.cpp line 2799:
> 2797: }
> 2798:
> 2799: Symbol* exception_name = throwable()->klass()->name();
Nit: extra space after `=`
src/hotspot/share/oops/cpCache.cpp line 478:
> 476: oop cause = java_lang_Throwable::cause(PENDING_EXCEPTION);
> 477: Symbol* cause_sym = NULL;
> 478: Symbol* cause_msg = NULL;
s/NULL/nullptr/
src/hotspot/share/oops/cpCache.cpp line 480:
> 478: Symbol* cause_msg = NULL;
> 479:
> 480: if (cause != NULL ) {
s/NULL/nullptr/
test/hotspot/jtreg/runtime/ClassInitErrors/TestNoClassDefFoundCause.java line 27:
> 25: * @test
> 26: * @bug 8302491
> 27: * @requires vm.compMode != "Xint"
Why?
test/hotspot/jtreg/runtime/ClassInitErrors/TestNoClassDefFoundCause.java line 28:
> 26: * @bug 8302491
> 27: * @requires vm.compMode != "Xint"
> 28: * @summary Test that StackOverflowError is correctly reporting in stack trace
s/reporting/reported/
-------------
Changes requested by dholmes (Reviewer).
PR: https://git.openjdk.org/jdk/pull/12566
More information about the hotspot-dev
mailing list