RFR (s) 8143269: Refactor code in universe_post_init that sets up methods to upcall
Coleen Phillimore
coleen.phillimore at oracle.com
Tue Mar 22 12:18:37 UTC 2016
Hi David,
Thank you for reviewing.
On 3/21/16 10:07 PM, David Holmes wrote:
> On 22/03/2016 12:05 AM, Coleen Phillimore wrote:
>> On 3/21/16 1:12 AM, David Holmes wrote:
>>> Hi Coleen,
>>>
>>> On 19/03/2016 10:57 PM, Coleen Phillimore wrote:
>>>> Summary: Deferred code review cleanups
>>>>
>>>> This was a review comment I had when the StackWalk API was integrated.
>>>> There were too many of this same code pattern in the middle of
>>>> universe_post_init. The only real change here is that if the method
>>>> isn't found and doesn't have the right linkage because of a
>>>> mismatch in
>>>> JDK version, we can vm_exit_during_initialization() rather than try to
>>>> return JNI_ERR. This avoids ugly code to check
>>>> initialize_known_method's boolean result for each call. We can't
>>>> throw
>>>> an exception here. Because of the EXCEPTION_MARK in
>>>> universe_post_init,
>>>> any exception gets turned into vm_exit_during_initialization
>>>> anyway. But
>>>> this wouldn't be a user error, so vm_exit_during_initialization seemed
>>>> like the cleanest choice.
>>>
>>> Our initialization code is truly awful. Until the VM is initialized
>>> any/all exceptions have to convert back to a different form of error
>>> because there will be no thread (or JVM for that matter) on which the
>>> user code could ask if an exception occurred. It then comes down to
>>> whether an error should be reported to the caller of JNI_CreateJavaVM
>>> so the host program doesn't get terminated, or we abort everything
>>> with vm_exit_during_initialization. And we're sliding further and
>>> further into always doing the latter.
>>>
>>> So in an absolute sense the new code is incompatible with the old
>>> because it will terminate host applications that wouldn't previously
>>> have been terminated - but in a practical sense this is unlikely to
>>> make any real difference to anything.
>>>
>>> That said something about all this is really bugging me. If we can do:
>>>
>>> ! SystemDictionary::Finalizer_klass()->link_class(CHECK_false);
>>>
>>> which purports to allow an exception to have been posted then how is
>>> it the immediately following code:
>>>
>>> ! Method* m = SystemDictionary::Finalizer_klass()->find_method(
>>> ! vmSymbols::register_method_name(),
>>> ! vmSymbols::register_method_signature());
>>> ! if (m == NULL || !m->is_static()) {
>>> ! tty->print_cr("Unable to link/verify Finalizer.register method");
>>> ! return false; // initialization failed (cannot throw exception
>>> yet)
>>> ! }
>>>
>>> can not throw an exception yet? Either both can throw or neither can
>>> throw AFAICS. So maybe the refactored link() call should not be using
>>> CHECK_ but also exit immediately?
>>
>> I don't think we should refactor InstanceKlass::link_class() for this.
>
> I wasn't suggesting that. As I said either both bits of code can throw
> exceptions or neither can, and I would have to assume it is the
> latter. link_class can be replaced by link_class_or_fail ie this:
>
> ik->link_class(CHECK);
> TempNewSymbol name = SymbolTable::new_symbol(method, CHECK);
> Method* m = ik->find_method(name, signature);
> if (m == NULL || is_static != m->is_static()) {
> ResourceMark rm(THREAD);
> vm_exit_during_initialization(err_msg("Unable to link/verify
> %s.%s method",
> ik->name()->as_C_string(), method));
> }
>
> becomes (hope I get this right):
>
> TempNewSymbol name = SymbolTable::new_symbol(method, CHECK);
> Method* m = NULL;
> if (!ik->link_class_or_fail(THREAD) ||
> ((m = ik->find_method(name, signature)) == NULL) ||
> is_static != m->is_static()) {
> ResourceMark rm(THREAD);
> vm_exit_during_initialization(err_msg("Unable to link/verify %s.%s
> method",
> ik->name()->as_C_string(), method));
> }
>
> The CHECK on new_symbol is still a pretense but ...
>
Yes, the CHECK in link_class is also a pretense. I added some dummy
code to throw a VerifyError and it got the assertion:
# assert(resolved_method->method_holder()->is_linked()) failed: must be
linked
From trying to call the Throwable.<clinit>. I thought we had fixed the
jvm to handle this better.
I think the code I had is easier to read, but in appreciation for your
code reviews, I've changed it to your if statement and retested.
http://cr.openjdk.java.net/~coleenp/8143269.02/webrev
>> I can rewrite so that every initialize_known_method call does:
>>
>> bool ok;
>> ok = initialize_known_method(<params>, CHECK);
>> if (!ok) return ok;
>>
>> ok = initialize_known_method(<params>, CHECK);
>> if (!ok) return ok;
>>
>> ...
>>
>> return true;
>>
>> Which I thought was really ugly and meaningless, since as I said, this
>> case is really an assert that the library doesn't match.
>
> I'm not sure why you are suggesting that. It would only make sense if
> if there were no vm_exit_during_initialization. ??
Right, which I thought was the objection.
>
> It would be interesting to see exactly when java_lang_Class is linked
> in relation to this code executing, so we could see when it would be
> possible to just throw the exceptions in all cases. Pity there seems
> to be no logging for class linking.
>
>> I could change it to an assert.
>>
>> Which is your preference? This is not my preference.
>
> I'm not sure what you would assert and where ??
>
I meant a fatal() call instead of vm_exit_during_initialization() since
the case that I'm calling it is an error in the JVM, not really from a
users perspective.
And YES, initialization is a messy business. Kim filed this bug a while
ago for one aspect of initialization. Throwing exceptions and/or
returning JNI_ERR is another aspect that makes it messy. Returning
JNI_ERR to some process embedding the JVM means that we've cleaned up
memory that we've allocated, of course, we haven't done that. I think
we have other bugs like that too.
https://bugs.openjdk.java.net/browse/JDK-8068392
Thanks,
Coleen
> Thanks,
> David
>
>> Thanks,
>> Coleen
>>>
>>>> Also, I want to get the code to not have to include method names (and
>>>> field names) in vmSymbols.cpp.
>>>>
>>>> I verified that this code won't merge conflict with jigsaw. There are
>>>> many additional cleanups that can be done here. universe_post_init
>>>> should really be a method belonging to Universe since it sets many
>>>> static fields in Universe, but to avoid merge conflicts, I didn't do
>>>> that.
>>>
>>> If you do that cleanup some time there are some very inaccurate
>>> comments in relation to the initialization code in init.cpp that could
>>> do with correcting. And I also spotted two paths to
>>> Interpreter::initialize.
>>>
>>> Thanks,
>>> David
>>> -----
>>>
>>>>
>>>> Tested with JPRT and colocated tests.
>>>>
>>>> open webrev at http://cr.openjdk.java.net/~coleenp/8143269.01/webrev
>>>> bug link https://bugs.openjdk.java.net/browse/JDK-8143269
>>>>
>>>> Thanks,
>>>> Coleen
>>
More information about the hotspot-runtime-dev
mailing list