Optimize JVM_GetDeclaringClass

David Holmes david.holmes at oracle.com
Wed Jun 10 04:13:37 UTC 2020


Hi Christoph,

I have filed:

https://bugs.openjdk.java.net/browse/JDK-8247296

for this enhancement.

In general you need to be careful about exposing naked oops when 
resolving these JNI handles, but it seems okay in this case.

I can also sponsor this for you, but there may be a short delay.

Cheers,
David
-----

On 10/06/2020 3:52 am, Christoph Dreis wrote:
> I've just stumbled upon JVM_GetDeclaringClass that I think could be optimized.
> The basic idea of the attached patch is to avoid repeated calls to JNIHandles::resolve_non_null & java_lang_Class::as_Klass.
> 
> With the following benchmark:
> 
> @BenchmarkMode(Mode.AverageTime)
> @OutputTimeUnit(TimeUnit.NANOSECONDS)
> public class MyBenchmark {
> 
>      @State(Scope.Benchmark)
>      public static class ThreadState {
>          private Class<?> clazz = ThreadState.class;
>      }
> 
>      @Benchmark
>      public Class<?> testClass(ThreadState threadState) {
>          return threadState.clazz.getDeclaringClass();
>      }
> 
> }
> 
> I see the following results:
> 
> BEFORE
> Benchmark                                Mode  Cnt    Score    Error   Units
> MyBenchmark.testClass         avgt   10  119,462 ±  3,914   ns/op
>                                                                
> PATCHED
> Benchmark                               Mode  Cnt    Score    Error   Units
> MyBenchmark.testClass         avgt   10  102,457 ±  4,746   ns/op
> 
> In case you think this is worthwhile, I would appreciate if someone can sponsor the patch.
> 
> Let me know what you think & if I'm missing something (my C++ is a bit rusted).
> (Because there seem to be similar optimizations possible throughout jvm.cpp.)
> 
> Cheers,
> Christoph
> 
> 
> ===== PATCH =====
> 
> --- a/src/hotspot/share/prims/jvm.cpp   Sat Jun 06 08:13:40 2020 +0000
> +++ b/src/hotspot/share/prims/jvm.cpp   Tue Jun 09 19:41:02 2020 +0200
> @@ -1560,15 +1560,17 @@
>   JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass))
>   {
>     // ofClass is a reference to a java_lang_Class object.
> -  if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
> -      ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) {
> +  oop mirror = JNIHandles::resolve_non_null(ofClass);
> +  if (java_lang_Class::is_primitive(mirror)) {
> +    return NULL;
> +  }
> +  Klass* k = java_lang_Class::as_Klass(mirror);
> +  if (!k->is_instance_klass()) {
>       return NULL;
>     }
> 
>     bool inner_is_member = false;
> -  Klass* outer_klass
> -    = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))
> -                          )->compute_enclosing_class(&inner_is_member, CHECK_NULL);
> +  Klass* outer_klass = InstanceKlass::cast(k)->compute_enclosing_class(&inner_is_member, CHECK_NULL);
>     if (outer_klass == NULL)  return NULL;  // already a top-level class
>     if (!inner_is_member)  return NULL;     // a hidden or unsafe anonymous class (inside a method)
>     return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror());


More information about the hotspot-runtime-dev mailing list