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