1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime.linker;
  27 
  28 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_FINAL;
  29 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE;
  30 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
  31 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
  32 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_VARARGS;
  34 import static jdk.internal.org.objectweb.asm.Opcodes.ACONST_NULL;
  35 import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
  36 import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE;
  37 import static jdk.internal.org.objectweb.asm.Opcodes.DUP;
  38 import static jdk.internal.org.objectweb.asm.Opcodes.IFNONNULL;
  39 import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
  40 import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
  41 import static jdk.internal.org.objectweb.asm.Opcodes.POP;
  42 import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
  43 import static jdk.nashorn.internal.lookup.Lookup.MH;
  44 import static jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome.ERROR_NO_ACCESSIBLE_CONSTRUCTOR;
  45 
  46 import java.lang.invoke.MethodHandle;
  47 import java.lang.invoke.MethodType;
  48 import java.lang.reflect.AccessibleObject;
  49 import java.lang.reflect.Constructor;
  50 import java.lang.reflect.Method;
  51 import java.lang.reflect.Modifier;
  52 import java.security.AccessControlContext;
  53 import java.security.AccessController;
  54 import java.security.PrivilegedAction;
  55 import java.util.Arrays;
  56 import java.util.Collection;
  57 import java.util.HashSet;
  58 import java.util.Iterator;
  59 import java.util.List;
  60 import java.util.Set;
  61 import jdk.internal.org.objectweb.asm.ClassWriter;
  62 import jdk.internal.org.objectweb.asm.Handle;
  63 import jdk.internal.org.objectweb.asm.Label;
  64 import jdk.internal.org.objectweb.asm.Opcodes;
  65 import jdk.internal.org.objectweb.asm.Type;
  66 import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
  67 import jdk.nashorn.internal.objects.Global;
  68 import jdk.nashorn.internal.runtime.Context;
  69 import jdk.nashorn.internal.runtime.ScriptFunction;
  70 import jdk.nashorn.internal.runtime.ScriptObject;
  71 import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
  72 import sun.reflect.CallerSensitive;
  73 
  74 /**
  75  * Generates bytecode for a Java adapter class. Used by the {@link JavaAdapterFactory}.
  76  * </p><p>
  77  * For every protected or public constructor in the extended class, the adapter class will have either one or two
  78  * public constructors (visibility of protected constructors in the extended class is promoted to public).
  79  * <li>
  80  * <li>For adapter classes with instance-level overrides, a constructor taking a trailing ScriptObject argument preceded
  81  * by original constructor arguments is always created on the adapter class. When such a constructor is invoked, the
  82  * passed ScriptObject's member functions are used to implement and/or override methods on the original class,
  83  * dispatched by name. A single JavaScript function will act as the implementation for all overloaded methods of the
  84  * same name. When methods on an adapter instance are invoked, the functions are invoked having the ScriptObject passed
  85  * in the instance constructor as their "this". Subsequent changes to the ScriptObject (reassignment or removal of its
  86  * functions) are not reflected in the adapter instance; the method implementations are bound to functions at
  87  * constructor invocation time.
  88  * {@code java.lang.Object} methods {@code equals}, {@code hashCode}, and {@code toString} can also be overridden. The
  89  * only restriction is that since every JavaScript object already has a {@code toString} function through the
  90  * {@code Object.prototype}, the {@code toString} in the adapter is only overridden if the passed ScriptObject has a
  91  * {@code toString} function as its own property, and not inherited from a prototype. All other adapter methods can be
  92  * implemented or overridden through a prototype-inherited function of the ScriptObject passed to the constructor too.
  93  * </li>
  94  * <li>
  95  * If the original types collectively have only one abstract method, or have several of them, but all share the
  96  * same name, an additional constructor for instance-level override adapter is provided for every original constructor;
  97  * this one takes a ScriptFunction as its last argument preceded by original constructor arguments. This constructor
  98  * will use the passed function as the implementation for all abstract methods. For consistency, any concrete methods
  99  * sharing the single abstract method name will also be overridden by the function. When methods on the adapter instance
 100  * are invoked, the ScriptFunction is invoked with UNDEFINED or Global as its "this" depending whether the function is
 101  * strict or not.
 102  * </li>
 103  * <li>
 104  * If the adapter being generated can have class-level overrides, constructors taking same arguments as the superclass
 105  * constructors are created. These constructors simply delegate to the superclass constructor. They are simply used to
 106  * create instances of the adapter class, with no instance-level overrides, as they don't have them.
 107  * </li>
 108  * </ul>
 109  * </p><p>
 110  * For adapter methods that return values, all the JavaScript-to-Java conversions supported by Nashorn will be in effect
 111  * to coerce the JavaScript function return value to the expected Java return type.
 112  * </p><p>
 113  * Since we are adding a trailing argument to the generated constructors in the adapter class, they will never be
 114  * declared as variable arity, even if the original constructor in the superclass was declared as variable arity. The
 115  * reason we are passing the additional argument at the end of the argument list instead at the front is that the
 116  * source-level script expression <code>new X(a, b) { ... }</code> (which is a proprietary syntax extension Nashorn uses
 117  * to resemble Java anonymous classes) is actually equivalent to <code>new X(a, b, { ... })</code>.
 118  * </p><p>
 119  * It is possible to create two different adapter classes: those that can have class-level overrides, and those that can
 120  * have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked
 121  * with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and
 122  * the passed script object will be used as the implementations for its methods, just as in the above case of the
 123  * constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on
 124  * every invocation, and the implementation object is bound to the class, not to any instance. All created instances
 125  * will share these functions. If it is required to have both class-level overrides and instance-level overrides, the
 126  * class-level override adapter class should be subclassed with an instance-override adapter. Since adapters delegate to
 127  * super class when an overriding method handle is not specified, this will behave as expected. It is not possible to
 128  * have both class-level and instance-level overrides in the same class for security reasons: adapter classes are
 129  * defined with a protection domain of their creator code, and an adapter class that has both class and instance level
 130  * overrides would need to have two potentially different protection domains: one for class-based behavior and one for
 131  * instance-based behavior; since Java classes can only belong to a single protection domain, this could not be
 132  * implemented securely.
 133  */
 134 final class JavaAdapterBytecodeGenerator {
 135     static final Type CONTEXT_TYPE       = Type.getType(Context.class);
 136     static final Type OBJECT_TYPE        = Type.getType(Object.class);
 137     static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class);
 138     static final Type GLOBAL_TYPE        = Type.getType(Global.class);
 139 
 140     static final String CONTEXT_TYPE_NAME = CONTEXT_TYPE.getInternalName();
 141     static final String OBJECT_TYPE_NAME  = OBJECT_TYPE.getInternalName();
 142 
 143     static final String INIT = "<init>";
 144 
 145     static final String GLOBAL_FIELD_NAME = "global";
 146 
 147     static final String SCRIPT_OBJECT_TYPE_DESCRIPTOR = SCRIPT_OBJECT_TYPE.getDescriptor();
 148     static final String GLOBAL_TYPE_DESCRIPTOR = GLOBAL_TYPE.getDescriptor();
 149 
 150     
 151     static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, GLOBAL_TYPE);
 152     static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE);
 153 
 154     private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class);
 155     private static final Type STRING_TYPE = Type.getType(String.class);
 156     private static final Type METHOD_TYPE_TYPE = Type.getType(MethodType.class);
 157     private static final Type METHOD_HANDLE_TYPE = Type.getType(MethodHandle.class);
 158     private static final String GET_HANDLE_OBJECT_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE,
 159             OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE);
 160     private static final String GET_HANDLE_FUNCTION_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE,
 161             SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE);
 162     private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(SCRIPT_OBJECT_TYPE);
 163     private static final Type RUNTIME_EXCEPTION_TYPE = Type.getType(RuntimeException.class);
 164     private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
 165     private static final Type UNSUPPORTED_OPERATION_TYPE = Type.getType(UnsupportedOperationException.class);
 166 
 167     private static final String SERVICES_CLASS_TYPE_NAME = Type.getInternalName(JavaAdapterServices.class);
 168     private static final String RUNTIME_EXCEPTION_TYPE_NAME = RUNTIME_EXCEPTION_TYPE.getInternalName();
 169     private static final String ERROR_TYPE_NAME = Type.getInternalName(Error.class);
 170     private static final String THROWABLE_TYPE_NAME = THROWABLE_TYPE.getInternalName();
 171     private static final String UNSUPPORTED_OPERATION_TYPE_NAME = UNSUPPORTED_OPERATION_TYPE.getInternalName();
 172 
 173     private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor();
 174     private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(GLOBAL_TYPE);
 175     private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class));
 176 
 177     // Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because
 178     // it's a java.* package.
 179     private static final String ADAPTER_PACKAGE_PREFIX = "jdk/nashorn/javaadapters/";
 180     // Class name suffix used to append to the adaptee class name, when it can be defined in the adaptee's package.
 181     private static final String ADAPTER_CLASS_NAME_SUFFIX = "$$NashornJavaAdapter";
 182     private static final String JAVA_PACKAGE_PREFIX = "java/";
 183     private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
 184 
 185     private static final String CLASS_INIT = "<clinit>";
 186 
 187     // Method name prefix for invoking super-methods
 188     static final String SUPER_PREFIX = "super$";
 189 
 190     /**
 191      * Collection of methods we never override: Object.clone(), Object.finalize().
 192      */
 193     private static final Collection<MethodInfo> EXCLUDED = getExcludedMethods();
 194 
 195     // This is the superclass for our generated adapter.
 196     private final Class<?> superClass;
 197     // Class loader used as the parent for the class loader we'll create to load the generated class. It will be a class
 198     // loader that has the visibility of all original types (class to extend and interfaces to implement) and of the
 199     // Nashorn classes.
 200     private final ClassLoader commonLoader;
 201     // Is this a generator for the version of the class that can have overrides on the class level?
 202     private final boolean classOverride;
 203     // Binary name of the superClass
 204     private final String superClassName;
 205     // Binary name of the generated class.
 206     private final String generatedClassName;
 207     private final Set<String> usedFieldNames = new HashSet<>();
 208     private final Set<String> abstractMethodNames = new HashSet<>();
 209     private final String samName;
 210     private final Set<MethodInfo> finalMethods = new HashSet<>(EXCLUDED);
 211     private final Set<MethodInfo> methodInfos = new HashSet<>();
 212     private boolean autoConvertibleFromFunction = false;
 213     private boolean hasExplicitFinalizer = false;
 214 
 215     private final ClassWriter cw;
 216 
 217     /**
 218      * Creates a generator for the bytecode for the adapter for the specified superclass and interfaces.
 219      * @param superClass the superclass the adapter will extend.
 220      * @param interfaces the interfaces the adapter will implement.
 221      * @param commonLoader the class loader that can see all of superClass, interfaces, and Nashorn classes.
 222      * @param classOverride true to generate the bytecode for the adapter that has class-level overrides, false to
 223      * generate the bytecode for the adapter that has instance-level overrides.
 224      * @throws AdaptationException if the adapter can not be generated for some reason.
 225      */
 226     JavaAdapterBytecodeGenerator(final Class<?> superClass, final List<Class<?>> interfaces,
 227             final ClassLoader commonLoader, final boolean classOverride) throws AdaptationException {
 228         assert superClass != null && !superClass.isInterface();
 229         assert interfaces != null;
 230 
 231         this.superClass = superClass;
 232         this.classOverride = classOverride;
 233         this.commonLoader = commonLoader;
 234         cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
 235             @Override
 236             protected String getCommonSuperClass(final String type1, final String type2) {
 237                 // We need to override ClassWriter.getCommonSuperClass to use this factory's commonLoader as a class
 238                 // loader to find the common superclass of two types when needed.
 239                 return JavaAdapterBytecodeGenerator.this.getCommonSuperClass(type1, type2);
 240             }
 241         };
 242         superClassName = Type.getInternalName(superClass);
 243         generatedClassName = getGeneratedClassName(superClass, interfaces);
 244 
 245         cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER, generatedClassName, null, superClassName, getInternalTypeNames(interfaces));
 246         generateGlobalFields();
 247 
 248         gatherMethods(superClass);
 249         gatherMethods(interfaces);
 250         samName = abstractMethodNames.size() == 1 ? abstractMethodNames.iterator().next() : null;
 251         generateHandleFields();
 252         if(classOverride) {
 253             generateClassInit();
 254         }
 255         generateConstructors();
 256         generateMethods();
 257         generateSuperMethods();
 258         if (hasExplicitFinalizer) {
 259             generateFinalizerMethods();
 260         }
 261         // }
 262         cw.visitEnd();
 263     }
 264 
 265     private void generateGlobalFields() {
 266         cw.visitField(ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0), GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR, null, null).visitEnd();
 267         usedFieldNames.add(GLOBAL_FIELD_NAME);
 268     }
 269 
 270     JavaAdapterClassLoader createAdapterClassLoader() {
 271         return new JavaAdapterClassLoader(generatedClassName, cw.toByteArray());
 272     }
 273 
 274     boolean isAutoConvertibleFromFunction() {
 275         return autoConvertibleFromFunction;
 276     }
 277 
 278     private static String getGeneratedClassName(final Class<?> superType, final List<Class<?>> interfaces) {
 279         // The class we use to primarily name our adapter is either the superclass, or if it is Object (meaning we're
 280         // just implementing interfaces or extending Object), then the first implemented interface or Object.
 281         final Class<?> namingType = superType == Object.class ? (interfaces.isEmpty()? Object.class : interfaces.get(0)) : superType;
 282         final Package pkg = namingType.getPackage();
 283         final String namingTypeName = Type.getInternalName(namingType);
 284         final StringBuilder buf = new StringBuilder();
 285         if (namingTypeName.startsWith(JAVA_PACKAGE_PREFIX) || pkg == null || pkg.isSealed()) {
 286             // Can't define new classes in java.* packages
 287             buf.append(ADAPTER_PACKAGE_PREFIX).append(namingTypeName);
 288         } else {
 289             buf.append(namingTypeName).append(ADAPTER_CLASS_NAME_SUFFIX);
 290         }
 291         final Iterator<Class<?>> it = interfaces.iterator();
 292         if(superType == Object.class && it.hasNext()) {
 293             it.next(); // Skip first interface, it was used to primarily name the adapter
 294         }
 295         // Append interface names to the adapter name
 296         while(it.hasNext()) {
 297             buf.append("$$").append(it.next().getSimpleName());
 298         }
 299         return buf.toString().substring(0, Math.min(MAX_GENERATED_TYPE_NAME_LENGTH, buf.length()));
 300     }
 301 
 302     /**
 303      * Given a list of class objects, return an array with their binary names. Used to generate the array of interface
 304      * names to implement.
 305      * @param classes the classes
 306      * @return an array of names
 307      */
 308     private static String[] getInternalTypeNames(final List<Class<?>> classes) {
 309         final int interfaceCount = classes.size();
 310         final String[] interfaceNames = new String[interfaceCount];
 311         for(int i = 0; i < interfaceCount; ++i) {
 312             interfaceNames[i] = Type.getInternalName(classes.get(i));
 313         }
 314         return interfaceNames;
 315     }
 316 
 317     private void generateHandleFields() {
 318         final int flags = ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0);
 319         for (final MethodInfo mi: methodInfos) {
 320             cw.visitField(flags, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd();
 321         }
 322     }
 323 
 324     private void generateClassInit() {
 325         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_STATIC, CLASS_INIT,
 326                 Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
 327 
 328         mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR, false);
 329         final Label initGlobal;
 330         if(samName != null) {
 331             // If the class is a SAM, allow having a ScriptFunction passed as class overrides
 332             final Label notAFunction = new Label();
 333             mv.dup();
 334             mv.instanceOf(SCRIPT_FUNCTION_TYPE);
 335             mv.ifeq(notAFunction);
 336             mv.checkcast(SCRIPT_FUNCTION_TYPE);
 337 
 338             // Assign MethodHandle fields through invoking getHandle() for a ScriptFunction, only assigning the SAM
 339             // method(s).
 340             for (final MethodInfo mi : methodInfos) {
 341                 if(mi.getName().equals(samName)) {
 342                     mv.dup();
 343                     mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
 344                     mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR, false);
 345                 } else {
 346                     mv.visitInsn(ACONST_NULL);
 347                 }
 348                 mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
 349             }
 350             initGlobal = new Label();
 351             mv.goTo(initGlobal);
 352             mv.visitLabel(notAFunction);
 353         } else {
 354             initGlobal = null;
 355         }
 356         // Assign MethodHandle fields through invoking getHandle() for a ScriptObject
 357         for (final MethodInfo mi : methodInfos) {
 358             mv.dup();
 359             mv.aconst(mi.getName());
 360             mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
 361             mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
 362             mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
 363         }
 364 
 365         if(initGlobal != null) {
 366             mv.visitLabel(initGlobal);
 367         }
 368         // Assign "global = Context.getGlobal()"
 369         invokeGetGlobalWithNullCheck(mv);
 370         mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
 371 
 372         endInitMethod(mv);
 373     }
 374 
 375     private static void invokeGetGlobalWithNullCheck(final InstructionAdapter mv) {
 376         invokeGetGlobal(mv);
 377         mv.dup();
 378         mv.invokevirtual(OBJECT_TYPE_NAME, "getClass", GET_CLASS_METHOD_DESCRIPTOR, false); // check against null Context
 379         mv.pop();
 380     }
 381 
 382     private void generateConstructors() throws AdaptationException {
 383         boolean gotCtor = false;
 384         for (final Constructor<?> ctor: superClass.getDeclaredConstructors()) {
 385             final int modifier = ctor.getModifiers();
 386             if((modifier & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0 && !isCallerSensitive(ctor)) {
 387                 generateConstructors(ctor);
 388                 gotCtor = true;
 389             }
 390         }
 391         if(!gotCtor) {
 392             throw new AdaptationException(ERROR_NO_ACCESSIBLE_CONSTRUCTOR, superClass.getCanonicalName());
 393         }
 394     }
 395 
 396     private void generateConstructors(final Constructor<?> ctor) {
 397         if(classOverride) {
 398             // Generate a constructor that just delegates to ctor. This is used with class-level overrides, when we want
 399             // to create instances without further per-instance overrides.
 400             generateDelegatingConstructor(ctor);
 401         } else {
 402             // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the
 403             // beginning of its parameter list.
 404             generateOverridingConstructor(ctor, false);
 405 
 406             if (samName != null) {
 407                 if (!autoConvertibleFromFunction && ctor.getParameterTypes().length == 0) {
 408                     // If the original type only has a single abstract method name, as well as a default ctor, then it can
 409                     // be automatically converted from JS function.
 410                     autoConvertibleFromFunction = true;
 411                 }
 412                 // If all our abstract methods have a single name, generate an additional constructor, one that takes a
 413                 // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
 414                 generateOverridingConstructor(ctor, true);
 415             }
 416         }
 417     }
 418 
 419     private void generateDelegatingConstructor(final Constructor<?> ctor) {
 420         final Type originalCtorType = Type.getType(ctor);
 421         final Type[] argTypes = originalCtorType.getArgumentTypes();
 422 
 423         // All constructors must be public, even if in the superclass they were protected.
 424         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
 425                 Type.getMethodDescriptor(originalCtorType.getReturnType(), argTypes), null, null));
 426 
 427         mv.visitCode();
 428         // Invoke super constructor with the same arguments.
 429         mv.visitVarInsn(ALOAD, 0);
 430         int offset = 1; // First arg is at position 1, after this.
 431         for (Type argType: argTypes) {
 432             mv.load(offset, argType);
 433             offset += argType.getSize();
 434         }
 435         mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor(), false);
 436 
 437         endInitMethod(mv);
 438     }
 439 
 440     /**
 441      * Generates a constructor for the instance adapter class. This constructor will take the same arguments as the supertype
 442      * constructor passed as the argument here, and delegate to it. However, it will take an additional argument of
 443      * either ScriptObject or ScriptFunction type (based on the value of the "fromFunction" parameter), and initialize
 444      * all the method handle fields of the adapter instance with functions from the script object (or the script
 445      * function itself, if that's what's passed). There is one method handle field in the adapter class for every method
 446      * that can be implemented or overridden; the name of every field is same as the name of the method, with a number
 447      * suffix that makes it unique in case of overloaded methods. The generated constructor will invoke
 448      * {@link #getHandle(ScriptFunction, MethodType, boolean)} or {@link #getHandle(Object, String, MethodType,
 449      * boolean)} to obtain the method handles; these methods make sure to add the necessary conversions and arity
 450      * adjustments so that the resulting method handles can be invoked from generated methods using {@code invokeExact}.
 451      * The constructor that takes a script function will only initialize the methods with the same name as the single
 452      * abstract method. The constructor will also store the Nashorn global that was current at the constructor
 453      * invocation time in a field named "global". The generated constructor will be public, regardless of whether the
 454      * supertype constructor was public or protected. The generated constructor will not be variable arity, even if the
 455      * supertype constructor was.
 456      * @param ctor the supertype constructor that is serving as the base for the generated constructor.
 457      * @param fromFunction true if we're generating a constructor that initializes SAM types from a single
 458      * ScriptFunction passed to it, false if we're generating a constructor that initializes an arbitrary type from a
 459      * ScriptObject passed to it.
 460      */
 461     private void generateOverridingConstructor(final Constructor<?> ctor, final boolean fromFunction) {
 462         final Type originalCtorType = Type.getType(ctor);
 463         final Type[] originalArgTypes = originalCtorType.getArgumentTypes();
 464         final int argLen = originalArgTypes.length;
 465         final Type[] newArgTypes = new Type[argLen + 1];
 466 
 467         // Insert ScriptFunction|Object as the last argument to the constructor
 468         final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : OBJECT_TYPE;
 469         newArgTypes[argLen] = extraArgumentType;
 470         System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen);
 471 
 472         // All constructors must be public, even if in the superclass they were protected.
 473         // Existing super constructor <init>(this, args...) triggers generating <init>(this, scriptObj, args...).
 474         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
 475                 Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
 476 
 477         mv.visitCode();
 478         // First, invoke super constructor with original arguments. If the form of the constructor we're generating is
 479         // <init>(this, args..., scriptFn), then we're invoking super.<init>(this, args...).
 480         mv.visitVarInsn(ALOAD, 0);
 481         final Class<?>[] argTypes = ctor.getParameterTypes();
 482         int offset = 1; // First arg is at position 1, after this.
 483         for (int i = 0; i < argLen; ++i) {
 484             final Type argType = Type.getType(argTypes[i]);
 485             mv.load(offset, argType);
 486             offset += argType.getSize();
 487         }
 488         mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor(), false);
 489 
 490         // Get a descriptor to the appropriate "JavaAdapterFactory.getHandle" method.
 491         final String getHandleDescriptor = fromFunction ? GET_HANDLE_FUNCTION_DESCRIPTOR : GET_HANDLE_OBJECT_DESCRIPTOR;
 492 
 493         // Assign MethodHandle fields through invoking getHandle()
 494         for (final MethodInfo mi : methodInfos) {
 495             mv.visitVarInsn(ALOAD, 0);
 496             if (fromFunction && !mi.getName().equals(samName)) {
 497                 // Constructors initializing from a ScriptFunction only initialize methods with the SAM name.
 498                 // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overriden too. This
 499                 // is a deliberate design choice. All other method handles are initialized to null.
 500                 mv.visitInsn(ACONST_NULL);
 501             } else {
 502                 mv.visitVarInsn(ALOAD, offset);
 503                 if(!fromFunction) {
 504                     mv.aconst(mi.getName());
 505                 }
 506                 mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
 507                 mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
 508             }
 509             mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
 510         }
 511 
 512         // Assign "this.global = Context.getGlobal()"
 513         mv.visitVarInsn(ALOAD, 0);
 514         invokeGetGlobalWithNullCheck(mv);
 515         mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
 516 
 517         endInitMethod(mv);
 518     }
 519 
 520     private static void endInitMethod(final InstructionAdapter mv) {
 521         mv.visitInsn(RETURN);
 522         endMethod(mv);
 523     }
 524 
 525     private static void endMethod(final InstructionAdapter mv) {
 526         mv.visitMaxs(0, 0);
 527         mv.visitEnd();
 528     }
 529 
 530     private static void invokeGetGlobal(final InstructionAdapter mv) {
 531         mv.invokestatic(CONTEXT_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false);
 532     }
 533 
 534     private static void invokeSetGlobal(final InstructionAdapter mv) {
 535         mv.invokestatic(CONTEXT_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false);
 536     }
 537 
 538     /**
 539      * Encapsulation of the information used to generate methods in the adapter classes. Basically, a wrapper around the
 540      * reflective Method object, a cached MethodType, and the name of the field in the adapter class that will hold the
 541      * method handle serving as the implementation of this method in adapter instances.
 542      *
 543      */
 544     private static class MethodInfo {
 545         private final Method method;
 546         private final MethodType type;
 547         private String methodHandleFieldName;
 548 
 549         private MethodInfo(final Class<?> clazz, final String name, final Class<?>... argTypes) throws NoSuchMethodException {
 550             this(clazz.getDeclaredMethod(name, argTypes));
 551         }
 552 
 553         private MethodInfo(final Method method) {
 554             this.method = method;
 555             this.type   = MH.type(method.getReturnType(), method.getParameterTypes());
 556         }
 557 
 558         @Override
 559         public boolean equals(final Object obj) {
 560             return obj instanceof MethodInfo && equals((MethodInfo)obj);
 561         }
 562 
 563         private boolean equals(final MethodInfo other) {
 564             // Only method name and type are used for comparison; method handle field name is not.
 565             return getName().equals(other.getName()) && type.equals(other.type);
 566         }
 567 
 568         String getName() {
 569             return method.getName();
 570         }
 571 
 572         @Override
 573         public int hashCode() {
 574             return getName().hashCode() ^ type.hashCode();
 575         }
 576 
 577         void setIsCanonical(final JavaAdapterBytecodeGenerator self) {
 578             methodHandleFieldName = self.nextName(getName());
 579         }
 580     }
 581 
 582     private String nextName(final String name) {
 583         int i = 0;
 584         String nextName = name;
 585         while (!usedFieldNames.add(nextName)) {
 586             final String ordinal = String.valueOf(i++);
 587             final int maxNameLen = 255 - ordinal.length();
 588             nextName = (name.length() <= maxNameLen ? name : name.substring(0, maxNameLen)).concat(ordinal);
 589         }
 590         return nextName;
 591     }
 592 
 593     private void generateMethods() {
 594         for(final MethodInfo mi: methodInfos) {
 595             generateMethod(mi);
 596         }
 597     }
 598 
 599     /**
 600      * Generates a method in the adapter class that adapts a method from the original class. The generated methods will
 601      * inspect the method handle field assigned to them. If it is null (the JS object doesn't provide an implementation
 602      * for the method) then it will either invoke its version in the supertype, or if it is abstract, throw an
 603      * {@link UnsupportedOperationException}. Otherwise, if the method handle field's value is not null, the handle is
 604      * invoked using invokeExact (signature polymorphic invocation as per JLS 15.12.3). Before the invocation, the
 605      * current Nashorn {@link Context} is checked, and if it is different than the global used to create the adapter
 606      * instance, the creating global is set to be the current global. In this case, the previously current global is
 607      * restored after the invocation. If invokeExact results in a Throwable that is not one of the method's declared
 608      * exceptions, and is not an unchecked throwable, then it is wrapped into a {@link RuntimeException} and the runtime
 609      * exception is thrown. The method handle retrieved from the field is guaranteed to exactly match the signature of
 610      * the method; this is guaranteed by the way constructors of the adapter class obtain them using
 611      * {@link #getHandle(Object, String, MethodType, boolean)}.
 612      * @param mi the method info describing the method to be generated.
 613      */
 614     private void generateMethod(final MethodInfo mi) {
 615         final Method method = mi.method;
 616         final Class<?>[] exceptions = method.getExceptionTypes();
 617         final String[] exceptionNames = getExceptionNames(exceptions);
 618         final MethodType type = mi.type;
 619         final String methodDesc = type.toMethodDescriptorString();
 620         final String name = mi.getName();
 621 
 622         final Type asmType = Type.getMethodType(methodDesc);
 623         final Type[] asmArgTypes = asmType.getArgumentTypes();
 624 
 625         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method), name,
 626                 methodDesc, null, exceptionNames));
 627         mv.visitCode();
 628 
 629         final Label handleDefined = new Label();
 630 
 631         final Type asmReturnType = Type.getType(type.returnType());
 632 
 633         // See if we have overriding method handle defined
 634         if(classOverride) {
 635             mv.getstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
 636         } else {
 637             mv.visitVarInsn(ALOAD, 0);
 638             mv.getfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
 639         }
 640         // stack: [handle]
 641         jumpIfNonNullKeepOperand(mv, handleDefined);
 642 
 643         // No handle is available, fall back to default behavior
 644         if(Modifier.isAbstract(method.getModifiers())) {
 645             // If the super method is abstract, throw an exception
 646             mv.anew(UNSUPPORTED_OPERATION_TYPE);
 647             mv.dup();
 648             mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR, false);
 649             mv.athrow();
 650         } else {
 651             // If the super method is not abstract, delegate to it.
 652             emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
 653         }
 654 
 655         mv.visitLabel(handleDefined);
 656         // Load the creatingGlobal object
 657         if(classOverride) {
 658             // If class handle is defined, load the static defining global
 659             mv.getstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
 660         } else {
 661             mv.visitVarInsn(ALOAD, 0);
 662             mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
 663         }
 664         // stack: [creatingGlobal, handle]
 665         final Label setupGlobal = new Label();
 666         mv.visitLabel(setupGlobal);
 667 
 668         // Determine the first index for a local variable
 669         int nextLocalVar = 1; // "this" is at 0
 670         for(final Type t: asmArgTypes) {
 671             nextLocalVar += t.getSize();
 672         }
 673         // Set our local variable indices
 674         final int currentGlobalVar  = nextLocalVar++;
 675         final int globalsDifferVar  = nextLocalVar++;
 676 
 677         mv.dup();
 678         // stack: [creatingGlobal, creatingGlobal, handle]
 679 
 680         // Emit code for switching to the creating global
 681         // Global currentGlobal = Context.getGlobal();
 682         invokeGetGlobal(mv);
 683         mv.dup();
 684 
 685         mv.visitVarInsn(ASTORE, currentGlobalVar);
 686         // stack: [currentGlobal, creatingGlobal, creatingGlobal, handle]
 687         // if(definingGlobal == currentGlobal) {
 688         final Label globalsDiffer = new Label();
 689         mv.ifacmpne(globalsDiffer);
 690         // stack: [creatingGlobal, handle]
 691         //     globalsDiffer = false
 692         mv.pop();
 693         // stack: [handle]
 694         mv.iconst(0); // false
 695         // stack: [false, handle]
 696         final Label invokeHandle = new Label();
 697         mv.goTo(invokeHandle);
 698         mv.visitLabel(globalsDiffer);
 699         // } else {
 700         //     Context.setGlobal(definingGlobal);
 701         // stack: [creatingGlobal, handle]
 702         invokeSetGlobal(mv);
 703         // stack: [handle]
 704         //     globalsDiffer = true
 705         mv.iconst(1);
 706         // stack: [true, handle]
 707 
 708         mv.visitLabel(invokeHandle);
 709         mv.visitVarInsn(ISTORE, globalsDifferVar);
 710         // stack: [handle]
 711 
 712         // Load all parameters back on stack for dynamic invocation.
 713         int varOffset = 1;
 714         for (final Type t : asmArgTypes) {
 715             mv.load(varOffset, t);
 716             varOffset += t.getSize();
 717         }
 718 
 719         // Invoke the target method handle
 720         final Label tryBlockStart = new Label();
 721         mv.visitLabel(tryBlockStart);
 722         mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
 723         final Label tryBlockEnd = new Label();
 724         mv.visitLabel(tryBlockEnd);
 725         emitFinally(mv, currentGlobalVar, globalsDifferVar);
 726         mv.areturn(asmReturnType);
 727 
 728         // If Throwable is not declared, we need an adapter from Throwable to RuntimeException
 729         final boolean throwableDeclared = isThrowableDeclared(exceptions);
 730         final Label throwableHandler;
 731         if (!throwableDeclared) {
 732             // Add "throw new RuntimeException(Throwable)" handler for Throwable
 733             throwableHandler = new Label();
 734             mv.visitLabel(throwableHandler);
 735             mv.anew(RUNTIME_EXCEPTION_TYPE);
 736             mv.dupX1();
 737             mv.swap();
 738             mv.invokespecial(RUNTIME_EXCEPTION_TYPE_NAME, INIT, Type.getMethodDescriptor(Type.VOID_TYPE, THROWABLE_TYPE), false);
 739             // Fall through to rethrow handler
 740         } else {
 741             throwableHandler = null;
 742         }
 743         final Label rethrowHandler = new Label();
 744         mv.visitLabel(rethrowHandler);
 745         // Rethrow handler for RuntimeException, Error, and all declared exception types
 746         emitFinally(mv, currentGlobalVar, globalsDifferVar);
 747         mv.athrow();
 748         final Label methodEnd = new Label();
 749         mv.visitLabel(methodEnd);
 750 
 751         mv.visitLocalVariable("currentGlobal", GLOBAL_TYPE_DESCRIPTOR, null, setupGlobal, methodEnd, currentGlobalVar);
 752         mv.visitLocalVariable("globalsDiffer", Type.INT_TYPE.getDescriptor(), null, setupGlobal, methodEnd, globalsDifferVar);
 753 
 754         if(throwableDeclared) {
 755             mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, THROWABLE_TYPE_NAME);
 756             assert throwableHandler == null;
 757         } else {
 758             mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, RUNTIME_EXCEPTION_TYPE_NAME);
 759             mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, ERROR_TYPE_NAME);
 760             for(final String excName: exceptionNames) {
 761                 mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, excName);
 762             }
 763             mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, throwableHandler, THROWABLE_TYPE_NAME);
 764         }
 765         endMethod(mv);
 766     }
 767 
 768     /**
 769      * Emits code for jumping to a label if the top stack operand is not null. The operand is kept on the stack if it
 770      * is not null (so is available to code at the jump address) and is popped if it is null.
 771      * @param mv the instruction adapter being used to emit code
 772      * @param label the label to jump to
 773      */
 774     private static void jumpIfNonNullKeepOperand(final InstructionAdapter mv, final Label label) {
 775         mv.visitInsn(DUP);
 776         mv.visitJumpInsn(IFNONNULL, label);
 777         mv.visitInsn(POP);
 778     }
 779 
 780     /**
 781      * Emit code to restore the previous Nashorn Context when needed.
 782      * @param mv the instruction adapter
 783      * @param currentGlobalVar index of the local variable holding the reference to the current global at method
 784      * entry.
 785      * @param globalsDifferVar index of the boolean local variable that is true if the global needs to be restored.
 786      */
 787     private static void emitFinally(final InstructionAdapter mv, final int currentGlobalVar, final int globalsDifferVar) {
 788         // Emit code to restore the previous Nashorn global if needed
 789         mv.visitVarInsn(ILOAD, globalsDifferVar);
 790         final Label skip = new Label();
 791         mv.ifeq(skip);
 792         mv.visitVarInsn(ALOAD, currentGlobalVar);
 793         invokeSetGlobal(mv);
 794         mv.visitLabel(skip);
 795     }
 796 
 797     private static boolean isThrowableDeclared(final Class<?>[] exceptions) {
 798         for (final Class<?> exception : exceptions) {
 799             if (exception == Throwable.class) {
 800                 return true;
 801             }
 802         }
 803         return false;
 804     }
 805 
 806     private void generateSuperMethods() {
 807         for(final MethodInfo mi: methodInfos) {
 808             if(!Modifier.isAbstract(mi.method.getModifiers())) {
 809                 generateSuperMethod(mi);
 810             }
 811         }
 812     }
 813 
 814     private void generateSuperMethod(MethodInfo mi) {
 815         final Method method = mi.method;
 816 
 817         final String methodDesc = mi.type.toMethodDescriptorString();
 818         final String name = mi.getName();
 819 
 820         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(getAccessModifiers(method),
 821                 SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
 822         mv.visitCode();
 823 
 824         emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
 825 
 826         endMethod(mv);
 827     }
 828 
 829     private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
 830         mv.visitVarInsn(ALOAD, 0);
 831         int nextParam = 1;
 832         final Type methodType = Type.getMethodType(methodDesc);
 833         for(final Type t: methodType.getArgumentTypes()) {
 834             mv.load(nextParam, t);
 835             nextParam += t.getSize();
 836         }
 837 
 838         // default method - non-abstract, interface method
 839         if (Modifier.isInterface(owner.getModifiers())) {
 840             mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
 841         } else {
 842             mv.invokespecial(superClassName, name, methodDesc, false);
 843         }
 844         mv.areturn(methodType.getReturnType());
 845     }
 846 
 847     private void generateFinalizerMethods() {
 848         final String finalizerDelegateName = nextName("access$");
 849         generateFinalizerDelegate(finalizerDelegateName);
 850         generateFinalizerOverride(finalizerDelegateName);
 851     }
 852 
 853     private void generateFinalizerDelegate(final String finalizerDelegateName) {
 854         // Generate a delegate that will be invoked from the no-permission trampoline. Note it can be private, as we'll
 855         // refer to it with a MethodHandle constant pool entry in the overridden finalize() method (see
 856         // generateFinalizerOverride()).
 857         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
 858                 finalizerDelegateName, Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE), null, null));
 859 
 860         // Simply invoke super.finalize()
 861         mv.visitVarInsn(ALOAD, 0);
 862         mv.checkcast(Type.getType(generatedClassName));
 863         mv.invokespecial(superClassName, "finalize", Type.getMethodDescriptor(Type.VOID_TYPE), false);
 864 
 865         mv.visitInsn(RETURN);
 866         endMethod(mv);
 867     }
 868 
 869     private void generateFinalizerOverride(final String finalizerDelegateName) {
 870         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, "finalize",
 871                 VOID_NOARG_METHOD_DESCRIPTOR, null, null));
 872         // Overridden finalizer will take a MethodHandle to the finalizer delegating method, ...
 873         mv.aconst(new Handle(Opcodes.H_INVOKESTATIC, generatedClassName, finalizerDelegateName,
 874                 Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE)));
 875         mv.visitVarInsn(ALOAD, 0);
 876         // ...and invoke it through JavaAdapterServices.invokeNoPermissions
 877         mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "invokeNoPermissions",
 878                 Type.getMethodDescriptor(METHOD_HANDLE_TYPE, OBJECT_TYPE), false);
 879         mv.visitInsn(RETURN);
 880         endMethod(mv);
 881     }
 882 
 883     private static String[] getExceptionNames(final Class<?>[] exceptions) {
 884         final String[] exceptionNames = new String[exceptions.length];
 885         for (int i = 0; i < exceptions.length; ++i) {
 886             exceptionNames[i] = Type.getInternalName(exceptions[i]);
 887         }
 888         return exceptionNames;
 889     }
 890 
 891     private static int getAccessModifiers(final Method method) {
 892         return ACC_PUBLIC | (method.isVarArgs() ? ACC_VARARGS : 0);
 893     }
 894 
 895     /**
 896      * Gathers methods that can be implemented or overridden from the specified type into this factory's
 897      * {@link #methodInfos} set. It will add all non-final, non-static methods that are either public or protected from
 898      * the type if the type itself is public. If the type is a class, the method will recursively invoke itself for its
 899      * superclass and the interfaces it implements, and add further methods that were not directly declared on the
 900      * class.
 901      * @param type the type defining the methods.
 902      */
 903     private void gatherMethods(final Class<?> type) throws AdaptationException {
 904         if (Modifier.isPublic(type.getModifiers())) {
 905             final Method[] typeMethods = type.isInterface() ? type.getMethods() : type.getDeclaredMethods();
 906 
 907             for (final Method typeMethod: typeMethods) {
 908                 final String name = typeMethod.getName();
 909                 if(name.startsWith(SUPER_PREFIX)) {
 910                     continue;
 911                 }
 912                 final int m = typeMethod.getModifiers();
 913                 if (Modifier.isStatic(m)) {
 914                     continue;
 915                 }
 916                 if (Modifier.isPublic(m) || Modifier.isProtected(m)) {
 917                     // Is it a "finalize()"?
 918                     if(name.equals("finalize") && typeMethod.getParameterCount() == 0) {
 919                         if(type != Object.class) {
 920                             hasExplicitFinalizer = true;
 921                             if(Modifier.isFinal(m)) {
 922                                 // Must be able to override an explicit finalizer
 923                                 throw new AdaptationException(Outcome.ERROR_FINAL_FINALIZER, type.getCanonicalName());
 924                             }
 925                         }
 926                         continue;
 927                     }
 928 
 929                     final MethodInfo mi = new MethodInfo(typeMethod);
 930                     if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) {
 931                         finalMethods.add(mi);
 932                     } else if (!finalMethods.contains(mi) && methodInfos.add(mi)) {
 933                         if (Modifier.isAbstract(m)) {
 934                             abstractMethodNames.add(mi.getName());
 935                         }
 936                         mi.setIsCanonical(this);
 937                     }
 938                 }
 939             }
 940         }
 941         // If the type is a class, visit its superclasses and declared interfaces. If it's an interface, we're done.
 942         // Needing to invoke the method recursively for a non-interface Class object is the consequence of needing to
 943         // see all declared protected methods, and Class.getDeclaredMethods() doesn't provide those declared in a
 944         // superclass. For interfaces, we used Class.getMethods(), as we're only interested in public ones there, and
 945         // getMethods() does provide those declared in a superinterface.
 946         if (!type.isInterface()) {
 947             final Class<?> superType = type.getSuperclass();
 948             if (superType != null) {
 949                 gatherMethods(superType);
 950             }
 951             for (final Class<?> itf: type.getInterfaces()) {
 952                 gatherMethods(itf);
 953             }
 954         }
 955     }
 956 
 957     private void gatherMethods(final List<Class<?>> classes) throws AdaptationException {
 958         for(final Class<?> c: classes) {
 959             gatherMethods(c);
 960         }
 961     }
 962 
 963     private static final AccessControlContext GET_DECLARED_MEMBERS_ACC_CTXT = ClassAndLoader.createPermAccCtxt("accessDeclaredMembers");
 964 
 965     /**
 966      * Creates a collection of methods that are not final, but we still never allow them to be overridden in adapters,
 967      * as explicitly declaring them automatically is a bad idea. Currently, this means {@code Object.finalize()} and
 968      * {@code Object.clone()}.
 969      * @return a collection of method infos representing those methods that we never override in adapter classes.
 970      */
 971     private static Collection<MethodInfo> getExcludedMethods() {
 972         return AccessController.doPrivileged(new PrivilegedAction<Collection<MethodInfo>>() {
 973             @Override
 974             public Collection<MethodInfo> run() {
 975                 try {
 976                     return Arrays.asList(
 977                             new MethodInfo(Object.class, "finalize"),
 978                             new MethodInfo(Object.class, "clone"));
 979                 } catch (final NoSuchMethodException e) {
 980                     throw new AssertionError(e);
 981                 }
 982             }
 983         }, GET_DECLARED_MEMBERS_ACC_CTXT);
 984     }
 985 
 986     private String getCommonSuperClass(final String type1, final String type2) {
 987         try {
 988             final Class<?> c1 = Class.forName(type1.replace('/', '.'), false, commonLoader);
 989             final Class<?> c2 = Class.forName(type2.replace('/', '.'), false, commonLoader);
 990             if (c1.isAssignableFrom(c2)) {
 991                 return type1;
 992             }
 993             if (c2.isAssignableFrom(c1)) {
 994                 return type2;
 995             }
 996             if (c1.isInterface() || c2.isInterface()) {
 997                 return OBJECT_TYPE_NAME;
 998             }
 999             return assignableSuperClass(c1, c2).getName().replace('.', '/');
1000         } catch(final ClassNotFoundException e) {
1001             throw new RuntimeException(e);
1002         }
1003     }
1004 
1005     private static Class<?> assignableSuperClass(final Class<?> c1, final Class<?> c2) {
1006         final Class<?> superClass = c1.getSuperclass();
1007         return superClass.isAssignableFrom(c2) ? superClass : assignableSuperClass(superClass, c2);
1008     }
1009 
1010     private static boolean isCallerSensitive(final AccessibleObject e) {
1011         return e.isAnnotationPresent(CallerSensitive.class);
1012     }
1013 }