< prev index next >

src/java.base/share/classes/jdk/internal/reflect/NativeMethodAccessorImpl.java

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
--- 1,7 ---
  /*
!  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

*** 23,19 ***
   * questions.
   */
  
  package jdk.internal.reflect;
  
! import java.lang.reflect.*;
  import jdk.internal.misc.Unsafe;
  
  /** Used only for the first few invocations of a Method; afterward,
      switches to bytecode-based implementation */
  
  class NativeMethodAccessorImpl extends MethodAccessorImpl {
!      private static final Unsafe U = Unsafe.getUnsafe();
!      private static final long GENERATED_OFFSET
          = U.objectFieldOffset(NativeMethodAccessorImpl.class, "generated");
  
      private final Method method;
      private final DelegatingMethodAccessorImpl parent;
      private int numInvocations;
--- 23,21 ---
   * questions.
   */
  
  package jdk.internal.reflect;
  
! import java.lang.reflect.InvocationTargetException;
+ import java.lang.reflect.Method;
  import jdk.internal.misc.Unsafe;
+ import sun.reflect.misc.ReflectUtil;
  
  /** Used only for the first few invocations of a Method; afterward,
      switches to bytecode-based implementation */
  
  class NativeMethodAccessorImpl extends MethodAccessorImpl {
!     private static final Unsafe U = Unsafe.getUnsafe();
!     private static final long GENERATED_OFFSET
          = U.objectFieldOffset(NativeMethodAccessorImpl.class, "generated");
  
      private final Method method;
      private final DelegatingMethodAccessorImpl parent;
      private int numInvocations;

*** 47,32 ***
      }
  
      public Object invoke(Object obj, Object[] args)
          throws IllegalArgumentException, InvocationTargetException
      {
!         // We can't inflate methods belonging to vm-anonymous classes because
!         // that kind of class can't be referred to by name, hence can't be
!         // found from the generated bytecode.
!         if (++numInvocations > ReflectionFactory.inflationThreshold()
!                 && !method.getDeclaringClass().isHidden()
!                 && generated == 0
!                 && U.compareAndSetInt(this, GENERATED_OFFSET, 0, 1)) {
              try {
!                 MethodAccessorImpl acc = (MethodAccessorImpl)
!                     new MethodAccessorGenerator().
!                         generateMethod(method.getDeclaringClass(),
!                                        method.getName(),
!                                        method.getParameterTypes(),
!                                        method.getReturnType(),
!                                        method.getExceptionTypes(),
!                                        method.getModifiers());
!                 parent.setDelegate(acc);
              } catch (Throwable t) {
!                 // Throwable happens in generateMethod, restore generated to 0
                  generated = 0;
                  throw t;
              }
          }
  
          return invoke0(method, obj, args);
      }
  
--- 49,51 ---
      }
  
      public Object invoke(Object obj, Object[] args)
          throws IllegalArgumentException, InvocationTargetException
      {
!         boolean generate = false;
!         if (!method.getDeclaringClass().isHidden()) {
!             if (Thread.currentThread().isVirtual()) {
!                 generate = true;
!             } else {
!                 if (++numInvocations > ReflectionFactory.inflationThreshold()
!                         && generated == 0
+                         && U.compareAndSetInt(this, GENERATED_OFFSET, 0, 1)) {
+                     generate = true;
+                 }
+             }
+         }
+ 
+         if (generate) {
+             Class<?> declaringClass = method.getDeclaringClass();
+ 
+             // class initializer may not have run
+             Unsafe.getUnsafe().ensureClassInitialized(declaringClass);
+ 
+             MethodAccessorImpl acc;
              try {
!                 // use bytecode generated implementation for @CS methods for now
!                 if (Reflection.isCallerSensitive(method)) {
!                     acc = (MethodAccessorImpl) new MethodAccessorGenerator()
!                                 .generateMethod(declaringClass,
!                                                 method.getName(),
!                                                 method.getParameterTypes(),
!                                                 method.getReturnType(),
!                                                 method.getExceptionTypes(),
!                                                 method.getModifiers());
+                 } else {
+                     acc = NewAccessorImplFactory.newMethodAccessorImpl(method);
+                 }
              } catch (Throwable t) {
!                 // generateMethod failed, restore generated to 0
                  generated = 0;
                  throw t;
              }
+ 
+             parent.setDelegate(acc);
+             return acc.invoke(obj, args);
          }
  
          return invoke0(method, obj, args);
      }
  
< prev index next >