示例#1
0
 public static Object convertArrayElements(Class<?> arrayType, Object array) {
   Class<?> src = array.getClass().getComponentType();
   Class<?> dst = arrayType.getComponentType();
   if (src == null || dst == null) throw new IllegalArgumentException("not array type");
   Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
   Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
   int length;
   if (sw == null) {
     Object[] a = (Object[]) array;
     length = a.length;
     if (dw == null) return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
     Object res = dw.makeArray(length);
     dw.copyArrayUnboxing(a, 0, res, 0, length);
     return res;
   }
   length = j86.java.lang.reflect.Array.getLength(array);
   Object[] res;
   if (dw == null) {
     res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
   } else {
     res = new Object[length];
   }
   sw.copyArrayBoxing(array, 0, res, 0, length);
   if (dw == null) return res;
   Object a = dw.makeArray(length);
   dw.copyArrayUnboxing(res, 0, a, 0, length);
   return a;
 }
示例#2
0
 /**
  * Finds method that accessible from specified class.
  *
  * @param method object that represents found method
  * @param generic generic type that is used to find accessible method
  * @return object that represents accessible method
  * @throws NoSuchMethodException if method is not accessible or is not found in specified
  *     superclass or interface
  */
 private static Method findAccessibleMethod(Method method, Type generic)
     throws NoSuchMethodException {
   String name = method.getName();
   Class<?>[] params = method.getParameterTypes();
   if (generic instanceof Class) {
     Class<?> type = (Class<?>) generic;
     return findAccessibleMethod(type.getMethod(name, params));
   }
   if (generic instanceof ParameterizedType) {
     ParameterizedType pt = (ParameterizedType) generic;
     Class<?> type = (Class<?>) pt.getRawType();
     for (Method m : type.getMethods()) {
       if (m.getName().equals(name)) {
         Class<?>[] pts = m.getParameterTypes();
         if (pts.length == params.length) {
           if (Arrays.equals(params, pts)) {
             return findAccessibleMethod(m);
           }
           Type[] gpts = m.getGenericParameterTypes();
           if (params.length == gpts.length) {
             if (Arrays.equals(params, TypeResolver.erase(TypeResolver.resolve(pt, gpts)))) {
               return findAccessibleMethod(m);
             }
           }
         }
       }
     }
   }
   throw new NoSuchMethodException("Method '" + name + "' is not accessible");
 }
示例#3
0
 /**
  * Constructs a <code>BatchUpdateException</code> object initialized with a given <code>reason
  * </code>, <code>SQLState</code>, <code>vendorCode</code> <code>cause</code> and <code>
  * updateCounts</code>.
  *
  * <p>This constructor should be used when the returned update count may exceed {@link
  * Integer#MAX_VALUE}.
  *
  * <p>
  *
  * @param reason a description of the error
  * @param SQLState an XOPEN or SQL:2003 code identifying the exception
  * @param vendorCode an exception code used by a particular database vendor
  * @param updateCounts an array of <code>long</code>, with each element indicating the update
  *     count, <code>Statement.SUCCESS_NO_INFO</code> or <code>Statement.EXECUTE_FAILED</code> for
  *     each SQL command in the batch for JDBC drivers that continue processing after a command
  *     failure; an update count or <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in
  *     the batch prior to the failure for JDBC drivers that stop processing after a command
  *     failure
  * @param cause the underlying reason for this <code>SQLException</code> (which is saved for later
  *     retrieval by the <code>getCause()</code> method); may be null indicating the cause is
  *     non-existent or unknown.
  * @since 1.8
  */
 public BatchUpdateException(
     String reason, String SQLState, int vendorCode, long[] updateCounts, Throwable cause) {
   super(reason, SQLState, vendorCode, cause);
   this.longUpdateCounts =
       (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
   this.updateCounts = (longUpdateCounts == null) ? null : copyUpdateCount(longUpdateCounts);
 }
示例#4
0
 /**
  * Return a method handle that takes the indicated number of typed arguments and returns an array
  * of them. The type argument is the array type.
  */
 public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
   Class<?> elemType = arrayType.getComponentType();
   if (elemType == null) throw new IllegalArgumentException("not an array: " + arrayType);
   // FIXME: Need more special casing and caching here.
   if (nargs >= MAX_JVM_ARITY / 2 - 1) {
     int slots = nargs;
     final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH
     if (arrayType == double[].class || arrayType == long[].class) slots *= 2;
     if (slots > MAX_ARRAY_SLOTS)
       throw new IllegalArgumentException(
           "too many arguments: " + arrayType.getSimpleName() + ", length " + nargs);
   }
   if (elemType == Object.class) return varargsArray(nargs);
   // other cases:  primitive arrays, subtypes of Object[]
   MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
   MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
   if (mh != null) return mh;
   if (elemType.isPrimitive()) {
     MethodHandle builder = FILL_NEW_ARRAY;
     MethodHandle producer = buildArrayProducer(arrayType);
     mh = buildVarargsArray(builder, producer, nargs);
   } else {
     @SuppressWarnings("unchecked")
     Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
     Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
     MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
     MethodHandle producer = ARRAY_IDENTITY;
     mh = buildVarargsArray(builder, producer, nargs);
   }
   mh =
       mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
   assert (assertCorrectArity(mh, nargs));
   if (nargs < cache.length) cache[nargs] = mh;
   return mh;
 }
示例#5
0
 /**
  * Returns the epochMonth found by locating the epochDay in the table. The epochMonth is the index
  * in the table
  *
  * @param epochDay
  * @return The index of the element of the start of the month containing the epochDay.
  */
 private int epochDayToEpochMonth(int epochDay) {
   // binary search
   int ndx = Arrays.binarySearch(hijrahEpochMonthStartDays, epochDay);
   if (ndx < 0) {
     ndx = -ndx - 2;
   }
   return ndx;
 }
示例#6
0
 @Override
 public int hashCode() {
   int result = 17;
   result = 37 * result + cksumType;
   if (checksum != null) {
     result = 37 * result + Arrays.hashCode(checksum);
   }
   return result;
 }
示例#7
0
 /**
  * Compares this finite field for equality with the specified object.
  *
  * @param obj the object to be compared.
  * @return true if {@code obj} is an instance of ECFieldF2m and both {@code m} and the reduction
  *     polynomial match, false otherwise.
  */
 public boolean equals(Object obj) {
   if (this == obj) return true;
   if (obj instanceof ECFieldF2m) {
     // no need to compare rp here since ks and rp
     // should be equivalent
     return ((m == ((ECFieldF2m) obj).m) && (Arrays.equals(ks, ((ECFieldF2m) obj).ks)));
   }
   return false;
 }
示例#8
0
 private static byte[][] genConst() {
   int n = 10;
   byte[][] arr = new byte[n][];
   for (int i = 0; i < n; i++) {
     byte[] b = new byte[i + 1];
     Arrays.fill(b, (byte) ('A' + i));
     arr[i] = b;
   }
   return arr;
 }
示例#9
0
 private String contentString() {
   StringBuilder sb = new StringBuilder("{");
   String sep = "";
   for (Map.Entry<String, Object> entry : contents.entrySet()) {
     sb.append(sep).append(entry.getKey()).append("=");
     String s = Arrays.deepToString(new Object[] {entry.getValue()});
     sb.append(s.substring(1, s.length() - 1));
     sep = ", ";
   }
   sb.append("}");
   return sb.toString();
 }
示例#10
0
  /**
   * This method may return false negatives. But if it says two names are equals, then there is some
   * mechanism that authenticates them as the same principal.
   */
  public boolean equals(GSSName other) throws GSSException {

    if (this.isAnonymous() || other.isAnonymous()) return false;

    if (other == this) return true;

    if (!(other instanceof GSSNameImpl))
      return equals(gssManager.createName(other.toString(), other.getStringNameType()));

    /*
     * XXX Do a comparison of the appNameStr/appNameBytes if
     * available. If that fails, then proceed with this test.
     */

    GSSNameImpl that = (GSSNameImpl) other;

    GSSNameSpi myElement = this.mechElement;
    GSSNameSpi element = that.mechElement;

    /*
     * XXX If they are not of the same mechanism type, convert both to
     * Kerberos since it is guaranteed to be present.
     */
    if ((myElement == null) && (element != null)) {
      myElement = this.getElement(element.getMechanism());
    } else if ((myElement != null) && (element == null)) {
      element = that.getElement(myElement.getMechanism());
    }

    if (myElement != null && element != null) {
      return myElement.equals(element);
    }

    if ((this.appNameType != null) && (that.appNameType != null)) {
      if (!this.appNameType.equals(that.appNameType)) {
        return false;
      }
      byte[] myBytes = null;
      byte[] bytes = null;
      try {
        myBytes = (this.appNameStr != null ? this.appNameStr.getBytes("UTF-8") : this.appNameBytes);
        bytes = (that.appNameStr != null ? that.appNameStr.getBytes("UTF-8") : that.appNameBytes);
      } catch (UnsupportedEncodingException e) {
        // Won't happen
      }

      return Arrays.equals(myBytes, bytes);
    }

    return false;
  }
示例#11
0
  /**
   * Returns the hash code value for this <code>CompositeDataSupport</code> instance.
   *
   * <p>The hash code of a <code>CompositeDataSupport</code> instance is the sum of the hash codes
   * of all elements of information used in <code>equals</code> comparisons (ie: its <i>composite
   * type</i> and all the item values).
   *
   * <p>This ensures that <code> t1.equals(t2) </code> implies that <code>
   *  t1.hashCode()==t2.hashCode() </code> for any two <code>CompositeDataSupport</code> instances
   * <code>t1</code> and <code>t2</code>, as required by the general contract of the method {@link
   * Object#hashCode() Object.hashCode()}.
   *
   * <p>Each item value's hash code is added to the returned hash code. If an item value is an
   * array, its hash code is obtained as if by calling the {@link
   * j86.java.util.Arrays#deepHashCode(Object[]) deepHashCode} method for arrays of object reference
   * types or the appropriate overloading of {@code Arrays.hashCode(e)} for arrays of primitive
   * types.
   *
   * @return the hash code value for this <code>CompositeDataSupport</code> instance
   */
  @Override
  public int hashCode() {
    int hashcode = compositeType.hashCode();

    for (Object o : contents.values()) {
      if (o instanceof Object[]) hashcode += Arrays.deepHashCode((Object[]) o);
      else if (o instanceof byte[]) hashcode += Arrays.hashCode((byte[]) o);
      else if (o instanceof short[]) hashcode += Arrays.hashCode((short[]) o);
      else if (o instanceof int[]) hashcode += Arrays.hashCode((int[]) o);
      else if (o instanceof long[]) hashcode += Arrays.hashCode((long[]) o);
      else if (o instanceof char[]) hashcode += Arrays.hashCode((char[]) o);
      else if (o instanceof float[]) hashcode += Arrays.hashCode((float[]) o);
      else if (o instanceof double[]) hashcode += Arrays.hashCode((double[]) o);
      else if (o instanceof boolean[]) hashcode += Arrays.hashCode((boolean[]) o);
      else if (o != null) hashcode += o.hashCode();
    }

    return hashcode;
  }
示例#12
0
  /**
   * Facilitates the creation of simple "function objects" that implement one or more interfaces by
   * delegation to a provided {@link MethodHandle}, after appropriate type adaptation and partial
   * evaluation of arguments. Typically used as a <em>bootstrap method</em> for {@code
   * invokedynamic} call sites, to support the <em>lambda expression</em> and <em>method reference
   * expression</em> features of the Java Programming Language.
   *
   * <p>This is the general, more flexible metafactory; a streamlined version is provided by {@link
   * #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}. A general description of
   * the behavior of this method is provided {@link LambdaMetafactory above}.
   *
   * <p>The argument list for this method includes three fixed parameters, corresponding to the
   * parameters automatically stacked by the VM for the bootstrap method in an {@code invokedynamic}
   * invocation, and an {@code Object[]} parameter that contains additional parameters. The declared
   * argument list for this method is:
   *
   * <pre>{@code
   * CallSite altMetafactory(MethodHandles.Lookup caller,
   *                         String invokedName,
   *                         MethodType invokedType,
   *                         Object... args)
   * }</pre>
   *
   * <p>but it behaves as if the argument list is as follows:
   *
   * <pre>{@code
   * CallSite altMetafactory(MethodHandles.Lookup caller,
   *                         String invokedName,
   *                         MethodType invokedType,
   *                         MethodType samMethodType,
   *                         MethodHandle implMethod,
   *                         MethodType instantiatedMethodType,
   *                         int flags,
   *                         int markerInterfaceCount,  // IF flags has MARKERS set
   *                         Class... markerInterfaces, // IF flags has MARKERS set
   *                         int bridgeCount,           // IF flags has BRIDGES set
   *                         MethodType... bridges      // IF flags has BRIDGES set
   *                         )
   * }</pre>
   *
   * <p>Arguments that appear in the argument list for {@link #metafactory(MethodHandles.Lookup,
   * String, MethodType, MethodType, MethodHandle, MethodType)} have the same specification as in
   * that method. The additional arguments are interpreted as follows:
   *
   * <ul>
   *   <li>{@code flags} indicates additional options; this is a bitwise OR of desired flags.
   *       Defined flags are {@link #FLAG_BRIDGES}, {@link #FLAG_MARKERS}, and {@link
   *       #FLAG_SERIALIZABLE}.
   *   <li>{@code markerInterfaceCount} is the number of additional interfaces the function object
   *       should implement, and is present if and only if the {@code FLAG_MARKERS} flag is set.
   *   <li>{@code markerInterfaces} is a variable-length list of additional interfaces to implement,
   *       whose length equals {@code markerInterfaceCount}, and is present if and only if the
   *       {@code FLAG_MARKERS} flag is set.
   *   <li>{@code bridgeCount} is the number of additional method signatures the function object
   *       should implement, and is present if and only if the {@code FLAG_BRIDGES} flag is set.
   *   <li>{@code bridges} is a variable-length list of additional methods signatures to implement,
   *       whose length equals {@code bridgeCount}, and is present if and only if the {@code
   *       FLAG_BRIDGES} flag is set.
   * </ul>
   *
   * <p>Each class named by {@code markerInterfaces} is subject to the same restrictions as {@code
   * Rd}, the return type of {@code invokedType}, as described {@link LambdaMetafactory above}. Each
   * {@code MethodType} named by {@code bridges} is subject to the same restrictions as {@code
   * samMethodType}, as described {@link LambdaMetafactory above}.
   *
   * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects will implement {@code
   * Serializable}, and will have a {@code writeReplace} method that returns an appropriate {@link
   * SerializedLambda}. The {@code caller} class must have an appropriate {@code
   * $deserializeLambda$} method, as described in {@link SerializedLambda}.
   *
   * <p>When the target of the {@code CallSite} returned from this method is invoked, the resulting
   * function objects are instances of a class with the following properties:
   *
   * <ul>
   *   <li>The class implements the interface named by the return type of {@code invokedType} and
   *       any interfaces named by {@code markerInterfaces}
   *   <li>The class declares methods with the name given by {@code invokedName}, and the signature
   *       given by {@code samMethodType} and additional signatures given by {@code bridges}
   *   <li>The class may override methods from {@code Object}, and may implement methods related to
   *       serialization.
   * </ul>
   *
   * @param caller Represents a lookup context with the accessibility privileges of the caller. When
   *     used with {@code invokedynamic}, this is stacked automatically by the VM.
   * @param invokedName The name of the method to implement. When used with {@code invokedynamic},
   *     this is provided by the {@code NameAndType} of the {@code InvokeDynamic} structure and is
   *     stacked automatically by the VM.
   * @param invokedType The expected signature of the {@code CallSite}. The parameter types
   *     represent the types of capture variables; the return type is the interface to implement.
   *     When used with {@code invokedynamic}, this is provided by the {@code NameAndType} of the
   *     {@code InvokeDynamic} structure and is stacked automatically by the VM. In the event that
   *     the implementation method is an instance method and this signature has any parameters, the
   *     first parameter in the invocation signature must correspond to the receiver.
   * @param args An {@code Object[]} array containing the required arguments {@code samMethodType},
   *     {@code implMethod}, {@code instantiatedMethodType}, {@code flags}, and any optional
   *     arguments, as described {@link #altMetafactory(MethodHandles.Lookup, String, MethodType,
   *     Object...)} above}
   * @return a CallSite whose target can be used to perform capture, generating instances of the
   *     interface named by {@code invokedType}
   * @throws LambdaConversionException If any of the linkage invariants described {@link
   *     LambdaMetafactory above} are violated
   */
  public static CallSite altMetafactory(
      MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object... args)
      throws LambdaConversionException {
    MethodType samMethodType = (MethodType) args[0];
    MethodHandle implMethod = (MethodHandle) args[1];
    MethodType instantiatedMethodType = (MethodType) args[2];
    int flags = (Integer) args[3];
    Class<?>[] markerInterfaces;
    MethodType[] bridges;
    int argIndex = 4;
    if ((flags & FLAG_MARKERS) != 0) {
      int markerCount = (Integer) args[argIndex++];
      markerInterfaces = new Class<?>[markerCount];
      System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
      argIndex += markerCount;
    } else markerInterfaces = EMPTY_CLASS_ARRAY;
    if ((flags & FLAG_BRIDGES) != 0) {
      int bridgeCount = (Integer) args[argIndex++];
      bridges = new MethodType[bridgeCount];
      System.arraycopy(args, argIndex, bridges, 0, bridgeCount);
      argIndex += bridgeCount;
    } else bridges = EMPTY_MT_ARRAY;

    boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
    if (isSerializable) {
      boolean foundSerializableSupertype =
          Serializable.class.isAssignableFrom(invokedType.returnType());
      for (Class<?> c : markerInterfaces)
        foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
      if (!foundSerializableSupertype) {
        markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
        markerInterfaces[markerInterfaces.length - 1] = Serializable.class;
      }
    }

    AbstractValidatingLambdaMetafactory mf =
        new InnerClassLambdaMetafactory(
            caller,
            invokedType,
            invokedName,
            samMethodType,
            implMethod,
            instantiatedMethodType,
            isSerializable,
            markerInterfaces,
            bridges);
    mf.validateMetafactoryArgs();
    return mf.buildCallSite();
  }
示例#13
0
 /**
  * Parses the 12 months lengths from a property value for a specific year.
  *
  * @param line the value of a year property
  * @return an array of int[12] containing the 12 month lengths
  * @throws IllegalArgumentException if the number of months is not 12
  * @throws NumberFormatException if the 12 tokens are not numbers
  */
 private int[] parseMonths(String line) {
   int[] months = new int[12];
   String[] numbers = line.split("\\s");
   if (numbers.length != 12) {
     throw new IllegalArgumentException(
         "wrong number of months on line: "
             + Arrays.toString(numbers)
             + "; count: "
             + numbers.length);
   }
   for (int i = 0; i < 12; i++) {
     try {
       months[i] = Integer.valueOf(numbers[i]);
     } catch (NumberFormatException nfe) {
       throw new IllegalArgumentException("bad key: " + numbers[i]);
     }
   }
   return months;
 }
示例#14
0
  /**
   * Compares the specified <var>obj</var> parameter with this <code>CompositeDataSupport</code>
   * instance for equality.
   *
   * <p>Returns <tt>true</tt> if and only if all of the following statements are true:
   *
   * <ul>
   *   <li><var>obj</var> is non null,
   *   <li><var>obj</var> also implements the <code>CompositeData</code> interface,
   *   <li>their composite types are equal
   *   <li>their contents, i.e. (name, value) pairs are equal. If a value contained in the content
   *       is an array, the value comparison is done as if by calling the {@link
   *       j86.java.util.Arrays#deepEquals(Object[], Object[]) deepEquals} method for arrays of
   *       object reference types or the appropriate overloading of {@code Arrays.equals(e1,e2)} for
   *       arrays of primitive types
   * </ul>
   *
   * <p>This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters
   * which are different implementations of the <code>CompositeData</code> interface, with the
   * restrictions mentioned in the {@link j86.java.util.Collection#equals(Object) equals} method of
   * the <tt>j86.java.util.Collection</tt> interface.
   *
   * @param obj the object to be compared for equality with this <code>CompositeDataSupport</code>
   *     instance.
   * @return <code>true</code> if the specified object is equal to this <code>CompositeDataSupport
   *     </code> instance.
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }

    // if obj is not a CompositeData, return false
    if (!(obj instanceof CompositeData)) {
      return false;
    }

    CompositeData other = (CompositeData) obj;

    // their compositeType should be equal
    if (!this.getCompositeType().equals(other.getCompositeType())) {
      return false;
    }

    if (contents.size() != other.values().size()) {
      return false;
    }

    for (Map.Entry<String, Object> entry : contents.entrySet()) {
      Object e1 = entry.getValue();
      Object e2 = other.get(entry.getKey());

      if (e1 == e2) continue;
      if (e1 == null) return false;

      boolean eq =
          e1.getClass().isArray()
              ? Arrays.deepEquals(new Object[] {e1}, new Object[] {e2})
              : e1.equals(e2);

      if (!eq) return false;
    }

    // All tests for equality were successful
    //
    return true;
  }
示例#15
0
 /**
  * Retrieves the update count for each update statement in the batch update that executed
  * successfully before this exception occurred. A driver that implements batch updates may or may
  * not continue to process the remaining commands in a batch when one of the commands fails to
  * execute properly. If the driver continues processing commands, the array returned by this
  * method will have as many elements as there are commands in the batch; otherwise, it will
  * contain an update count for each command that executed successfully before the <code>
  * BatchUpdateException</code> was thrown.
  *
  * <p>The possible return values for this method were modified for the Java 2 SDK, Standard
  * Edition, version 1.3. This was done to accommodate the new option of continuing to process
  * commands in a batch update after a <code>BatchUpdateException</code> object has been thrown.
  *
  * @return an array of <code>int</code> containing the update counts for the updates that were
  *     executed successfully before this error occurred. Or, if the driver continues to process
  *     commands after an error, one of the following for every command in the batch:
  *     <OL>
  *       <LI>an update count
  *       <LI><code>Statement.SUCCESS_NO_INFO</code> to indicate that the command executed
  *           successfully but the number of rows affected is unknown
  *       <LI><code>Statement.EXECUTE_FAILED</code> to indicate that the command failed to execute
  *           successfully
  *     </OL>
  *
  * @since 1.3
  * @see #getLargeUpdateCounts()
  */
 public int[] getUpdateCounts() {
   return (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
 }
示例#16
0
 public SF2Instrument[] getInstruments() {
   SF2Instrument[] inslist_array = instruments.toArray(new SF2Instrument[instruments.size()]);
   Arrays.sort(inslist_array, new ModelInstrumentComparator());
   return inslist_array;
 }
示例#17
0
public class ValueConversions {
  private static final Class<?> THIS_CLASS = ValueConversions.class;
  // Do not adjust this except for special platforms:
  private static final int MAX_ARITY;

  static {
    final Object[] values = {255};
    AccessController.doPrivileged(
        new PrivilegedAction<Void>() {
          @Override
          public Void run() {
            values[0] = Integer.getInteger(THIS_CLASS.getName() + ".MAX_ARITY", 255);
            return null;
          }
        });
    MAX_ARITY = (Integer) values[0];
  }

  private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();

  private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
    @SuppressWarnings("unchecked") // generic array creation
    EnumMap<Wrapper, MethodHandle>[] caches =
        (EnumMap<Wrapper, MethodHandle>[]) new EnumMap<?, ?>[n];
    for (int i = 0; i < n; i++) caches[i] = new EnumMap<>(Wrapper.class);
    return caches;
  }

  /// Converting references to values.

  // There are several levels of this unboxing conversions:
  //   no conversions:  exactly Integer.valueOf, etc.
  //   implicit conversions sanctioned by JLS 5.1.2, etc.
  //   explicit conversions as allowed by explicitCastArguments

  static int unboxInteger(Object x, boolean cast) {
    if (x instanceof Integer) return ((Integer) x).intValue();
    return primitiveConversion(Wrapper.INT, x, cast).intValue();
  }

  static byte unboxByte(Object x, boolean cast) {
    if (x instanceof Byte) return ((Byte) x).byteValue();
    return primitiveConversion(Wrapper.BYTE, x, cast).byteValue();
  }

  static short unboxShort(Object x, boolean cast) {
    if (x instanceof Short) return ((Short) x).shortValue();
    return primitiveConversion(Wrapper.SHORT, x, cast).shortValue();
  }

  static boolean unboxBoolean(Object x, boolean cast) {
    if (x instanceof Boolean) return ((Boolean) x).booleanValue();
    return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0;
  }

  static char unboxCharacter(Object x, boolean cast) {
    if (x instanceof Character) return ((Character) x).charValue();
    return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue();
  }

  static long unboxLong(Object x, boolean cast) {
    if (x instanceof Long) return ((Long) x).longValue();
    return primitiveConversion(Wrapper.LONG, x, cast).longValue();
  }

  static float unboxFloat(Object x, boolean cast) {
    if (x instanceof Float) return ((Float) x).floatValue();
    return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue();
  }

  static double unboxDouble(Object x, boolean cast) {
    if (x instanceof Double) return ((Double) x).doubleValue();
    return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue();
  }

  private static MethodType unboxType(Wrapper wrap) {
    return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
  }

  private static final EnumMap<Wrapper, MethodHandle>[] UNBOX_CONVERSIONS = newWrapperCaches(2);

  private static MethodHandle unbox(Wrapper wrap, boolean cast) {
    EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast ? 1 : 0)];
    MethodHandle mh = cache.get(wrap);
    if (mh != null) {
      return mh;
    }
    // slow path
    switch (wrap) {
      case OBJECT:
        mh = IDENTITY;
        break;
      case VOID:
        mh = IGNORE;
        break;
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }
    // look up the method
    String name = "unbox" + wrap.wrapperSimpleName();
    MethodType type = unboxType(wrap);
    try {
      mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
    } catch (ReflectiveOperationException ex) {
      mh = null;
    }
    if (mh != null) {
      mh = MethodHandles.insertArguments(mh, 1, cast);
      cache.put(wrap, mh);
      return mh;
    }
    throw new IllegalArgumentException(
        "cannot find unbox adapter for " + wrap + (cast ? " (cast)" : ""));
  }

  public static MethodHandle unboxCast(Wrapper type) {
    return unbox(type, true);
  }

  public static MethodHandle unbox(Class<?> type) {
    return unbox(Wrapper.forPrimitiveType(type), false);
  }

  public static MethodHandle unboxCast(Class<?> type) {
    return unbox(Wrapper.forPrimitiveType(type), true);
  }

  private static final Integer ZERO_INT = 0, ONE_INT = 1;

  /// Primitive conversions
  /**
   * Produce a Number which represents the given value {@code x} according to the primitive type of
   * the given wrapper {@code wrap}. Caller must invoke intValue, byteValue, longValue (etc.) on the
   * result to retrieve the desired primitive value.
   */
  public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
    // Maybe merge this code with Wrapper.convert/cast.
    Number res;
    if (x == null) {
      if (!cast) return null;
      return ZERO_INT;
    }
    if (x instanceof Number) {
      res = (Number) x;
    } else if (x instanceof Boolean) {
      res = ((boolean) x ? ONE_INT : ZERO_INT);
    } else if (x instanceof Character) {
      res = (int) (char) x;
    } else {
      // this will fail with the required ClassCastException:
      res = (Number) x;
    }
    Wrapper xwrap = Wrapper.findWrapperType(x.getClass());
    if (xwrap == null || !cast && !wrap.isConvertibleFrom(xwrap))
      // this will fail with the required ClassCastException:
      return (Number) wrap.wrapperType().cast(x);
    return res;
  }

  /**
   * The JVM verifier allows boolean, byte, short, or char to widen to int. Support exactly this
   * conversion, from a boxed value type Boolean, Byte, Short, Character, or Integer.
   */
  public static int widenSubword(Object x) {
    if (x instanceof Integer) return (int) x;
    else if (x instanceof Boolean) return fromBoolean((boolean) x);
    else if (x instanceof Character) return (char) x;
    else if (x instanceof Short) return (short) x;
    else if (x instanceof Byte) return (byte) x;
    else
      // Fail with a ClassCastException.
      return (int) x;
  }

  /// Converting primitives to references

  static Integer boxInteger(int x) {
    return x;
  }

  static Byte boxByte(byte x) {
    return x;
  }

  static Short boxShort(short x) {
    return x;
  }

  static Boolean boxBoolean(boolean x) {
    return x;
  }

  static Character boxCharacter(char x) {
    return x;
  }

  static Long boxLong(long x) {
    return x;
  }

  static Float boxFloat(float x) {
    return x;
  }

  static Double boxDouble(double x) {
    return x;
  }

  private static MethodType boxType(Wrapper wrap) {
    // be exact, since return casts are hard to compose
    Class<?> boxType = wrap.wrapperType();
    return MethodType.methodType(boxType, wrap.primitiveType());
  }

  private static final EnumMap<Wrapper, MethodHandle>[] BOX_CONVERSIONS = newWrapperCaches(2);

  private static MethodHandle box(Wrapper wrap, boolean exact) {
    EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact ? 1 : 0)];
    MethodHandle mh = cache.get(wrap);
    if (mh != null) {
      return mh;
    }
    // slow path
    switch (wrap) {
      case OBJECT:
        mh = IDENTITY;
        break;
      case VOID:
        mh = ZERO_OBJECT;
        break;
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }
    // look up the method
    String name = "box" + wrap.wrapperSimpleName();
    MethodType type = boxType(wrap);
    if (exact) {
      try {
        mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
      } catch (ReflectiveOperationException ex) {
        mh = null;
      }
    } else {
      mh = box(wrap, !exact).asType(type.erase());
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }
    throw new IllegalArgumentException(
        "cannot find box adapter for " + wrap + (exact ? " (exact)" : ""));
  }

  public static MethodHandle box(Class<?> type) {
    boolean exact = false;
    // e.g., boxShort(short)Short if exact,
    // e.g., boxShort(short)Object if !exact
    return box(Wrapper.forPrimitiveType(type), exact);
  }

  public static MethodHandle box(Wrapper type) {
    boolean exact = false;
    return box(type, exact);
  }

  /// Constant functions

  static void ignore(Object x) {
    // no value to return; this is an unbox of null
  }

  static void empty() {}

  static Object zeroObject() {
    return null;
  }

  static int zeroInteger() {
    return 0;
  }

  static long zeroLong() {
    return 0;
  }

  static float zeroFloat() {
    return 0;
  }

  static double zeroDouble() {
    return 0;
  }

  private static final EnumMap<Wrapper, MethodHandle>[] CONSTANT_FUNCTIONS = newWrapperCaches(2);

  public static MethodHandle zeroConstantFunction(Wrapper wrap) {
    EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
    MethodHandle mh = cache.get(wrap);
    if (mh != null) {
      return mh;
    }
    // slow path
    MethodType type = MethodType.methodType(wrap.primitiveType());
    switch (wrap) {
      case VOID:
        mh = EMPTY;
        break;
      case OBJECT:
      case INT:
      case LONG:
      case FLOAT:
      case DOUBLE:
        try {
          mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero" + wrap.wrapperSimpleName(), type);
        } catch (ReflectiveOperationException ex) {
          mh = null;
        }
        break;
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }

    // use zeroInt and cast the result
    if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
      mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
      cache.put(wrap, mh);
      return mh;
    }
    throw new IllegalArgumentException("cannot find zero constant for " + wrap);
  }

  /// Converting references to references.

  /**
   * Identity function.
   *
   * @param x an arbitrary reference value
   * @return the same value x
   */
  static <T> T identity(T x) {
    return x;
  }

  static <T> T[] identity(T[] x) {
    return x;
  }

  /**
   * Identity function on ints.
   *
   * @param x an arbitrary int value
   * @return the same value x
   */
  static int identity(int x) {
    return x;
  }

  static byte identity(byte x) {
    return x;
  }

  static short identity(short x) {
    return x;
  }

  static boolean identity(boolean x) {
    return x;
  }

  static char identity(char x) {
    return x;
  }

  /**
   * Identity function on longs.
   *
   * @param x an arbitrary long value
   * @return the same value x
   */
  static long identity(long x) {
    return x;
  }

  static float identity(float x) {
    return x;
  }

  static double identity(double x) {
    return x;
  }

  /**
   * Identity function, with reference cast.
   *
   * @param t an arbitrary reference type
   * @param x an arbitrary reference value
   * @return the same value x
   */
  @SuppressWarnings("unchecked")
  static <T, U> T castReference(Class<? extends T> t, U x) {
    // inlined Class.cast because we can't ForceInline it
    if (x != null && !t.isInstance(x)) throw newClassCastException(t, x);
    return (T) x;
  }

  private static ClassCastException newClassCastException(Class<?> t, Object obj) {
    return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
  }

  private static final MethodHandle IDENTITY,
      CAST_REFERENCE,
      ZERO_OBJECT,
      IGNORE,
      EMPTY,
      ARRAY_IDENTITY,
      FILL_NEW_TYPED_ARRAY,
      FILL_NEW_ARRAY;

  static {
    try {
      MethodType idType = MethodType.genericMethodType(1);
      MethodType castType = idType.insertParameterTypes(0, Class.class);
      MethodType ignoreType = idType.changeReturnType(void.class);
      MethodType zeroObjectType = MethodType.genericMethodType(0);
      IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
      // CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
      CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
      ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
      IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
      EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
      ARRAY_IDENTITY =
          IMPL_LOOKUP.findStatic(
              THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
      FILL_NEW_ARRAY =
          IMPL_LOOKUP.findStatic(
              THIS_CLASS,
              "fillNewArray",
              MethodType.methodType(Object[].class, Integer.class, Object[].class));
      FILL_NEW_TYPED_ARRAY =
          IMPL_LOOKUP.findStatic(
              THIS_CLASS,
              "fillNewTypedArray",
              MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
    } catch (NoSuchMethodException | IllegalAccessException ex) {
      throw newInternalError("uncaught exception", ex);
    }
  }

  // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
  static class LazyStatics {
    private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;

    static {
      try {
        // MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray",
        // MethodType.methodType(Object[].class, Object[].class));
        COPY_AS_REFERENCE_ARRAY =
            IMPL_LOOKUP.findStatic(
                THIS_CLASS,
                "copyAsReferenceArray",
                MethodType.methodType(Object[].class, Class.class, Object[].class));
        COPY_AS_PRIMITIVE_ARRAY =
            IMPL_LOOKUP.findStatic(
                THIS_CLASS,
                "copyAsPrimitiveArray",
                MethodType.methodType(Object.class, Wrapper.class, Object[].class));
        MAKE_LIST =
            IMPL_LOOKUP.findStatic(
                THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
      } catch (ReflectiveOperationException ex) {
        throw newInternalError("uncaught exception", ex);
      }
    }
  }

  private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS = newWrapperCaches(1);

  /**
   * Return a method that casts its sole argument (an Object) to the given type and returns it as
   * the given type.
   */
  public static MethodHandle cast(Class<?> type) {
    if (type.isPrimitive())
      throw new IllegalArgumentException("cannot cast primitive type " + type);
    MethodHandle mh;
    Wrapper wrap = null;
    EnumMap<Wrapper, MethodHandle> cache = null;
    if (Wrapper.isWrapperType(type)) {
      wrap = Wrapper.forWrapperType(type);
      cache = WRAPPER_CASTS[0];
      mh = cache.get(wrap);
      if (mh != null) return mh;
    }
    mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
    if (cache != null) cache.put(wrap, mh);
    return mh;
  }

  public static MethodHandle identity() {
    return IDENTITY;
  }

  public static MethodHandle identity(Class<?> type) {
    if (!type.isPrimitive())
      // Reference identity has been moved into MethodHandles:
      return MethodHandles.identity(type);
    return identity(Wrapper.findPrimitiveType(type));
  }

  public static MethodHandle identity(Wrapper wrap) {
    EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
    MethodHandle mh = cache.get(wrap);
    if (mh != null) {
      return mh;
    }
    // slow path
    MethodType type = MethodType.methodType(wrap.primitiveType());
    if (wrap != Wrapper.VOID) type = type.appendParameterTypes(wrap.primitiveType());
    try {
      mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type);
    } catch (ReflectiveOperationException ex) {
      mh = null;
    }
    if (mh == null && wrap == Wrapper.VOID) {
      mh = EMPTY; // #(){} : #()void
    }
    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }

    if (mh != null) {
      cache.put(wrap, mh);
      return mh;
    }
    throw new IllegalArgumentException("cannot find identity for " + wrap);
  }

  /// Primitive conversions.
  // These are supported directly by the JVM, usually by a single instruction.
  // In the case of narrowing to a subword, there may be a pair of instructions.
  // In the case of booleans, there may be a helper routine to manage a 1-bit value.
  // This is the full 8x8 matrix (minus the diagonal).

  // narrow double to all other types:
  static float doubleToFloat(double x) { // bytecode: d2f
    return (float) x;
  }

  static long doubleToLong(double x) { // bytecode: d2l
    return (long) x;
  }

  static int doubleToInt(double x) { // bytecode: d2i
    return (int) x;
  }

  static short doubleToShort(double x) { // bytecodes: d2i, i2s
    return (short) x;
  }

  static char doubleToChar(double x) { // bytecodes: d2i, i2c
    return (char) x;
  }

  static byte doubleToByte(double x) { // bytecodes: d2i, i2b
    return (byte) x;
  }

  static boolean doubleToBoolean(double x) {
    return toBoolean((byte) x);
  }

  // widen float:
  static double floatToDouble(float x) { // bytecode: f2d
    return x;
  }
  // narrow float:
  static long floatToLong(float x) { // bytecode: f2l
    return (long) x;
  }

  static int floatToInt(float x) { // bytecode: f2i
    return (int) x;
  }

  static short floatToShort(float x) { // bytecodes: f2i, i2s
    return (short) x;
  }

  static char floatToChar(float x) { // bytecodes: f2i, i2c
    return (char) x;
  }

  static byte floatToByte(float x) { // bytecodes: f2i, i2b
    return (byte) x;
  }

  static boolean floatToBoolean(float x) {
    return toBoolean((byte) x);
  }

  // widen long:
  static double longToDouble(long x) { // bytecode: l2d
    return x;
  }

  static float longToFloat(long x) { // bytecode: l2f
    return x;
  }
  // narrow long:
  static int longToInt(long x) { // bytecode: l2i
    return (int) x;
  }

  static short longToShort(long x) { // bytecodes: f2i, i2s
    return (short) x;
  }

  static char longToChar(long x) { // bytecodes: f2i, i2c
    return (char) x;
  }

  static byte longToByte(long x) { // bytecodes: f2i, i2b
    return (byte) x;
  }

  static boolean longToBoolean(long x) {
    return toBoolean((byte) x);
  }

  // widen int:
  static double intToDouble(int x) { // bytecode: i2d
    return x;
  }

  static float intToFloat(int x) { // bytecode: i2f
    return x;
  }

  static long intToLong(int x) { // bytecode: i2l
    return x;
  }
  // narrow int:
  static short intToShort(int x) { // bytecode: i2s
    return (short) x;
  }

  static char intToChar(int x) { // bytecode: i2c
    return (char) x;
  }

  static byte intToByte(int x) { // bytecode: i2b
    return (byte) x;
  }

  static boolean intToBoolean(int x) {
    return toBoolean((byte) x);
  }

  // widen short:
  static double shortToDouble(short x) { // bytecode: i2d (implicit 's2i')
    return x;
  }

  static float shortToFloat(short x) { // bytecode: i2f (implicit 's2i')
    return x;
  }

  static long shortToLong(short x) { // bytecode: i2l (implicit 's2i')
    return x;
  }

  static int shortToInt(short x) { // (implicit 's2i')
    return x;
  }
  // narrow short:
  static char shortToChar(short x) { // bytecode: i2c (implicit 's2i')
    return (char) x;
  }

  static byte shortToByte(short x) { // bytecode: i2b (implicit 's2i')
    return (byte) x;
  }

  static boolean shortToBoolean(short x) {
    return toBoolean((byte) x);
  }

  // widen char:
  static double charToDouble(char x) { // bytecode: i2d (implicit 'c2i')
    return x;
  }

  static float charToFloat(char x) { // bytecode: i2f (implicit 'c2i')
    return x;
  }

  static long charToLong(char x) { // bytecode: i2l (implicit 'c2i')
    return x;
  }

  static int charToInt(char x) { // (implicit 'c2i')
    return x;
  }
  // narrow char:
  static short charToShort(char x) { // bytecode: i2s (implicit 'c2i')
    return (short) x;
  }

  static byte charToByte(char x) { // bytecode: i2b (implicit 'c2i')
    return (byte) x;
  }

  static boolean charToBoolean(char x) {
    return toBoolean((byte) x);
  }

  // widen byte:
  static double byteToDouble(byte x) { // bytecode: i2d (implicit 'b2i')
    return x;
  }

  static float byteToFloat(byte x) { // bytecode: i2f (implicit 'b2i')
    return x;
  }

  static long byteToLong(byte x) { // bytecode: i2l (implicit 'b2i')
    return x;
  }

  static int byteToInt(byte x) { // (implicit 'b2i')
    return x;
  }

  static short byteToShort(byte x) { // bytecode: i2s (implicit 'b2i')
    return (short) x;
  }

  static char byteToChar(byte x) { // bytecode: i2b (implicit 'b2i')
    return (char) x;
  }
  // narrow byte to boolean:
  static boolean byteToBoolean(byte x) {
    return toBoolean(x);
  }

  // widen boolean to all types:
  static double booleanToDouble(boolean x) {
    return fromBoolean(x);
  }

  static float booleanToFloat(boolean x) {
    return fromBoolean(x);
  }

  static long booleanToLong(boolean x) {
    return fromBoolean(x);
  }

  static int booleanToInt(boolean x) {
    return fromBoolean(x);
  }

  static short booleanToShort(boolean x) {
    return fromBoolean(x);
  }

  static char booleanToChar(boolean x) {
    return (char) fromBoolean(x);
  }

  static byte booleanToByte(boolean x) {
    return fromBoolean(x);
  }

  // helpers to force boolean into the conversion scheme:
  static boolean toBoolean(byte x) {
    // see javadoc for MethodHandles.explicitCastArguments
    return ((x & 1) != 0);
  }

  static byte fromBoolean(boolean x) {
    // see javadoc for MethodHandles.explicitCastArguments
    return (x ? (byte) 1 : (byte) 0);
  }

  private static final EnumMap<Wrapper, MethodHandle>[] CONVERT_PRIMITIVE_FUNCTIONS =
      newWrapperCaches(Wrapper.values().length);

  public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
    EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
    MethodHandle mh = cache.get(wdst);
    if (mh != null) {
      return mh;
    }
    // slow path
    Class<?> src = wsrc.primitiveType();
    Class<?> dst = wdst.primitiveType();
    MethodType type =
        src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src);
    if (wsrc == wdst) {
      mh = identity(src);
    } else if (wsrc == Wrapper.VOID) {
      mh = zeroConstantFunction(wdst);
    } else if (wdst == Wrapper.VOID) {
      mh = MethodHandles.dropArguments(EMPTY, 0, src); // Defer back to MethodHandles.
    } else if (wsrc == Wrapper.OBJECT) {
      mh = unboxCast(dst);
    } else if (wdst == Wrapper.OBJECT) {
      mh = box(src);
    } else {
      assert (src.isPrimitive() && dst.isPrimitive());
      try {
        mh =
            IMPL_LOOKUP.findStatic(
                THIS_CLASS, src.getSimpleName() + "To" + capitalize(dst.getSimpleName()), type);
      } catch (ReflectiveOperationException ex) {
        mh = null;
      }
    }
    if (mh != null) {
      assert (mh.type() == type) : mh;
      cache.put(wdst, mh);
      return mh;
    }

    throw new IllegalArgumentException(
        "cannot find primitive conversion function for "
            + src.getSimpleName()
            + " -> "
            + dst.getSimpleName());
  }

  public static MethodHandle convertPrimitive(Class<?> src, Class<?> dst) {
    return convertPrimitive(Wrapper.forPrimitiveType(src), Wrapper.forPrimitiveType(dst));
  }

  private static String capitalize(String x) {
    return Character.toUpperCase(x.charAt(0)) + x.substring(1);
  }

  /// Collection of multiple arguments.

  public static Object convertArrayElements(Class<?> arrayType, Object array) {
    Class<?> src = array.getClass().getComponentType();
    Class<?> dst = arrayType.getComponentType();
    if (src == null || dst == null) throw new IllegalArgumentException("not array type");
    Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
    Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
    int length;
    if (sw == null) {
      Object[] a = (Object[]) array;
      length = a.length;
      if (dw == null) return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
      Object res = dw.makeArray(length);
      dw.copyArrayUnboxing(a, 0, res, 0, length);
      return res;
    }
    length = j86.java.lang.reflect.Array.getLength(array);
    Object[] res;
    if (dw == null) {
      res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
    } else {
      res = new Object[length];
    }
    sw.copyArrayBoxing(array, 0, res, 0, length);
    if (dw == null) return res;
    Object a = dw.makeArray(length);
    dw.copyArrayUnboxing(res, 0, a, 0, length);
    return a;
  }

  private static MethodHandle findCollector(
      String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
    MethodType type =
        MethodType.genericMethodType(nargs).changeReturnType(rtype).insertParameterTypes(0, ptypes);
    try {
      return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
    } catch (ReflectiveOperationException ex) {
      return null;
    }
  }

  private static final Object[] NO_ARGS_ARRAY = {};

  private static Object[] makeArray(Object... args) {
    return args;
  }

  private static Object[] array() {
    return NO_ARGS_ARRAY;
  }

  private static Object[] array(Object a0) {
    return makeArray(a0);
  }

  private static Object[] array(Object a0, Object a1) {
    return makeArray(a0, a1);
  }

  private static Object[] array(Object a0, Object a1, Object a2) {
    return makeArray(a0, a1, a2);
  }

  private static Object[] array(Object a0, Object a1, Object a2, Object a3) {
    return makeArray(a0, a1, a2, a3);
  }

  private static Object[] array(Object a0, Object a1, Object a2, Object a3, Object a4) {
    return makeArray(a0, a1, a2, a3, a4);
  }

  private static Object[] array(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) {
    return makeArray(a0, a1, a2, a3, a4, a5);
  }

  private static Object[] array(
      Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
    return makeArray(a0, a1, a2, a3, a4, a5, a6);
  }

  private static Object[] array(
      Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
    return makeArray(a0, a1, a2, a3, a4, a5, a6, a7);
  }

  private static Object[] array(
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7,
      Object a8) {
    return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8);
  }

  private static Object[] array(
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7,
      Object a8,
      Object a9) {
    return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  }

  private static MethodHandle[] makeArrays() {
    ArrayList<MethodHandle> mhs = new ArrayList<>();
    for (; ; ) {
      MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
      if (mh == null) break;
      mhs.add(mh);
    }
    assert (mhs.size() == 11); // current number of methods
    return mhs.toArray(new MethodHandle[MAX_ARITY + 1]);
  }

  private static final MethodHandle[] ARRAYS = makeArrays();

  // filling versions of the above:
  // using Integer len instead of int len and no varargs to avoid bootstrapping problems
  private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
    Object[] a = new Object[len];
    fillWithArguments(a, 0, args);
    return a;
  }

  private static Object[] fillNewTypedArray(
      Object[] example, Integer len, Object[] /*not ...*/ args) {
    Object[] a = Arrays.copyOf(example, len);
    fillWithArguments(a, 0, args);
    return a;
  }

  private static void fillWithArguments(Object[] a, int pos, Object... args) {
    System.arraycopy(args, 0, a, pos, args.length);
  }
  // using Integer pos instead of int pos to avoid bootstrapping problems
  private static Object[] fillArray(Integer pos, Object[] a, Object a0) {
    fillWithArguments(a, pos, a0);
    return a;
  }

  private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) {
    fillWithArguments(a, pos, a0, a1);
    return a;
  }

  private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) {
    fillWithArguments(a, pos, a0, a1, a2);
    return a;
  }

  private static Object[] fillArray(
      Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) {
    fillWithArguments(a, pos, a0, a1, a2, a3);
    return a;
  }

  private static Object[] fillArray(
      Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4) {
    fillWithArguments(a, pos, a0, a1, a2, a3, a4);
    return a;
  }

  private static Object[] fillArray(
      Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) {
    fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5);
    return a;
  }

  private static Object[] fillArray(
      Integer pos,
      Object[] a,
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6) {
    fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6);
    return a;
  }

  private static Object[] fillArray(
      Integer pos,
      Object[] a,
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7) {
    fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7);
    return a;
  }

  private static Object[] fillArray(
      Integer pos,
      Object[] a,
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7,
      Object a8) {
    fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8);
    return a;
  }

  private static Object[] fillArray(
      Integer pos,
      Object[] a,
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7,
      Object a8,
      Object a9) {
    fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
    return a;
  }

  private static MethodHandle[] makeFillArrays() {
    ArrayList<MethodHandle> mhs = new ArrayList<>();
    mhs.add(null); // there is no empty fill; at least a0 is required
    for (; ; ) {
      MethodHandle mh =
          findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
      if (mh == null) break;
      mhs.add(mh);
    }
    assert (mhs.size() == 11); // current number of methods
    return mhs.toArray(new MethodHandle[0]);
  }

  private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();

  private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
    return Arrays.copyOf(a, a.length, arrayType);
  }

  private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
    Object a = w.makeArray(boxes.length);
    w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
    return a;
  }

  /**
   * Return a method handle that takes the indicated number of Object arguments and returns an
   * Object array of them, as if for varargs.
   */
  public static MethodHandle varargsArray(int nargs) {
    MethodHandle mh = ARRAYS[nargs];
    if (mh != null) return mh;
    mh = findCollector("array", nargs, Object[].class);
    if (mh != null) return ARRAYS[nargs] = mh;
    mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
    assert (assertCorrectArity(mh, nargs));
    return ARRAYS[nargs] = mh;
  }

  private static boolean assertCorrectArity(MethodHandle mh, int arity) {
    assert (mh.type().parameterCount() == arity) : "arity != " + arity + ": " + mh;
    return true;
  }

  private static MethodHandle buildVarargsArray(
      MethodHandle newArray, MethodHandle finisher, int nargs) {
    // Build up the result mh as a sequence of fills like this:
    //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
    // The various fill(_,10*I,___*[J]) are reusable.
    int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately
    int rightLen = nargs - leftLen;
    MethodHandle leftCollector = newArray.bindTo(nargs);
    leftCollector = leftCollector.asCollector(Object[].class, leftLen);
    MethodHandle mh = finisher;
    if (rightLen > 0) {
      MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
      if (mh == ARRAY_IDENTITY) mh = rightFiller;
      else mh = MethodHandles.collectArguments(mh, 0, rightFiller);
    }
    if (mh == ARRAY_IDENTITY) mh = leftCollector;
    else mh = MethodHandles.collectArguments(mh, 0, leftCollector);
    return mh;
  }

  private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
  private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY + 1];
  /**
   * fill_array_to_right(N).invoke(a, argL..arg[N-1]) fills a[L]..a[N-1] with corresponding
   * arguments, and then returns a. The value L is a global constant (LEFT_ARGS).
   */
  private static MethodHandle fillToRight(int nargs) {
    MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
    if (filler != null) return filler;
    filler = buildFiller(nargs);
    assert (assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
    return FILL_ARRAY_TO_RIGHT[nargs] = filler;
  }

  private static MethodHandle buildFiller(int nargs) {
    if (nargs <= LEFT_ARGS) return ARRAY_IDENTITY; // no args to fill; return the array unchanged
    // we need room for both mh and a in mh.invoke(a, arg*[nargs])
    final int CHUNK = LEFT_ARGS;
    int rightLen = nargs % CHUNK;
    int midLen = nargs - rightLen;
    if (rightLen == 0) {
      midLen = nargs - (rightLen = CHUNK);
      if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
        // build some precursors from left to right
        for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) if (j > LEFT_ARGS) fillToRight(j);
      }
    }
    if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
    assert (rightLen > 0);
    MethodHandle midFill = fillToRight(midLen); // recursive fill
    MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1]
    assert (midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS);
    assert (rightFill.type().parameterCount() == 1 + rightLen);

    // Combine the two fills:
    //   right(mid(a, x10..x19), x20..x23)
    // The final product will look like this:
    //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
    if (midLen == LEFT_ARGS) return rightFill;
    else return MethodHandles.collectArguments(rightFill, 0, midFill);
  }

  // Type-polymorphic version of varargs maker.
  private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS =
      new ClassValue<MethodHandle[]>() {
        @Override
        protected MethodHandle[] computeValue(Class<?> type) {
          return new MethodHandle[256];
        }
      };

  static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM

  /**
   * Return a method handle that takes the indicated number of typed arguments and returns an array
   * of them. The type argument is the array type.
   */
  public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
    Class<?> elemType = arrayType.getComponentType();
    if (elemType == null) throw new IllegalArgumentException("not an array: " + arrayType);
    // FIXME: Need more special casing and caching here.
    if (nargs >= MAX_JVM_ARITY / 2 - 1) {
      int slots = nargs;
      final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH
      if (arrayType == double[].class || arrayType == long[].class) slots *= 2;
      if (slots > MAX_ARRAY_SLOTS)
        throw new IllegalArgumentException(
            "too many arguments: " + arrayType.getSimpleName() + ", length " + nargs);
    }
    if (elemType == Object.class) return varargsArray(nargs);
    // other cases:  primitive arrays, subtypes of Object[]
    MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
    MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
    if (mh != null) return mh;
    if (elemType.isPrimitive()) {
      MethodHandle builder = FILL_NEW_ARRAY;
      MethodHandle producer = buildArrayProducer(arrayType);
      mh = buildVarargsArray(builder, producer, nargs);
    } else {
      @SuppressWarnings("unchecked")
      Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
      Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
      MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
      MethodHandle producer = ARRAY_IDENTITY;
      mh = buildVarargsArray(builder, producer, nargs);
    }
    mh =
        mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
    assert (assertCorrectArity(mh, nargs));
    if (nargs < cache.length) cache[nargs] = mh;
    return mh;
  }

  private static MethodHandle buildArrayProducer(Class<?> arrayType) {
    Class<?> elemType = arrayType.getComponentType();
    if (elemType.isPrimitive())
      return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType));
    else return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType);
  }

  // List version of varargs maker.

  private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);

  private static List<Object> makeList(Object... args) {
    return Arrays.asList(args);
  }

  private static List<Object> list() {
    return NO_ARGS_LIST;
  }

  private static List<Object> list(Object a0) {
    return makeList(a0);
  }

  private static List<Object> list(Object a0, Object a1) {
    return makeList(a0, a1);
  }

  private static List<Object> list(Object a0, Object a1, Object a2) {
    return makeList(a0, a1, a2);
  }

  private static List<Object> list(Object a0, Object a1, Object a2, Object a3) {
    return makeList(a0, a1, a2, a3);
  }

  private static List<Object> list(Object a0, Object a1, Object a2, Object a3, Object a4) {
    return makeList(a0, a1, a2, a3, a4);
  }

  private static List<Object> list(
      Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) {
    return makeList(a0, a1, a2, a3, a4, a5);
  }

  private static List<Object> list(
      Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
    return makeList(a0, a1, a2, a3, a4, a5, a6);
  }

  private static List<Object> list(
      Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
    return makeList(a0, a1, a2, a3, a4, a5, a6, a7);
  }

  private static List<Object> list(
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7,
      Object a8) {
    return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8);
  }

  private static List<Object> list(
      Object a0,
      Object a1,
      Object a2,
      Object a3,
      Object a4,
      Object a5,
      Object a6,
      Object a7,
      Object a8,
      Object a9) {
    return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  }

  private static MethodHandle[] makeLists() {
    ArrayList<MethodHandle> mhs = new ArrayList<>();
    for (; ; ) {
      MethodHandle mh = findCollector("list", mhs.size(), List.class);
      if (mh == null) break;
      mhs.add(mh);
    }
    assert (mhs.size() == 11); // current number of methods
    return mhs.toArray(new MethodHandle[MAX_ARITY + 1]);
  }

  private static final MethodHandle[] LISTS = makeLists();

  /**
   * Return a method handle that takes the indicated number of Object arguments and returns a List.
   */
  public static MethodHandle varargsList(int nargs) {
    MethodHandle mh = LISTS[nargs];
    if (mh != null) return mh;
    mh = findCollector("list", nargs, List.class);
    if (mh != null) return LISTS[nargs] = mh;
    return LISTS[nargs] = buildVarargsList(nargs);
  }

  private static MethodHandle buildVarargsList(int nargs) {
    return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST);
  }

  // handy shared exception makers (they simplify the common case code)
  private static InternalError newInternalError(String message, Throwable cause) {
    return new InternalError(message, cause);
  }

  private static InternalError newInternalError(Throwable cause) {
    return new InternalError(cause);
  }
}
示例#18
0
 private static List<Object> makeList(Object... args) {
   return Arrays.asList(args);
 }
示例#19
0
 /**
  * Retrieves the update count for each update statement in the batch update that executed
  * successfully before this exception occurred. A driver that implements batch updates may or may
  * not continue to process the remaining commands in a batch when one of the commands fails to
  * execute properly. If the driver continues processing commands, the array returned by this
  * method will have as many elements as there are commands in the batch; otherwise, it will
  * contain an update count for each command that executed successfully before the <code>
  * BatchUpdateException</code> was thrown.
  *
  * <p>This method should be used when {@code Statement.executeLargeBatch} is invoked and the
  * returned update count may exceed {@link Integer#MAX_VALUE}.
  *
  * <p>
  *
  * @return an array of <code>long</code> containing the update counts for the updates that were
  *     executed successfully before this error occurred. Or, if the driver continues to process
  *     commands after an error, one of the following for every command in the batch:
  *     <OL>
  *       <LI>an update count
  *       <LI><code>Statement.SUCCESS_NO_INFO</code> to indicate that the command executed
  *           successfully but the number of rows affected is unknown
  *       <LI><code>Statement.EXECUTE_FAILED</code> to indicate that the command failed to execute
  *           successfully
  *     </OL>
  *
  * @since 1.8
  */
 public long[] getLargeUpdateCounts() {
   return (longUpdateCounts == null)
       ? null
       : Arrays.copyOf(longUpdateCounts, longUpdateCounts.length);
 }
示例#20
0
 @Override
 public List<Era> eras() {
   return Arrays.<Era>asList(HijrahEra.values());
 }
示例#21
0
  /**
   * Constructs a MessageToken from an InputStream. Bytes will be read on demand and the thread
   * might block if there are not enough bytes to complete the token. Please note there is no
   * accurate way to find out the size of a token, but we try our best to make sure there is enough
   * bytes to construct one.
   *
   * @param tokenId the token id that should be contained in this token as it is read.
   * @param context the Kerberos context associated with this token
   * @param is the InputStream from which to read
   * @param prop the MessageProp structure in which the properties of the token should be stored.
   * @throws GSSException if there is a problem reading from the InputStream or parsing the token
   */
  MessageToken_v2(int tokenId, Krb5Context context, InputStream is, MessageProp prop)
      throws GSSException {
    init(tokenId, context);

    try {
      if (!confState) {
        prop.setPrivacy(false);
      }
      tokenHeader = new MessageTokenHeader(is, prop, tokenId);

      // set key_usage
      if (tokenId == Krb5Token.WRAP_ID_v2) {
        key_usage = (!initiator ? KG_USAGE_INITIATOR_SEAL : KG_USAGE_ACCEPTOR_SEAL);
      } else if (tokenId == Krb5Token.MIC_ID_v2) {
        key_usage = (!initiator ? KG_USAGE_INITIATOR_SIGN : KG_USAGE_ACCEPTOR_SIGN);
      }

      int minSize = 0; // minimal size for token data
      if (tokenId == Krb5Token.WRAP_ID_v2 && prop.getPrivacy()) {
        minSize = CONFOUNDER_SIZE + TOKEN_HEADER_SIZE + cipherHelper.getChecksumLength();
      } else {
        minSize = cipherHelper.getChecksumLength();
      }

      // Read token data
      if (tokenId == Krb5Token.MIC_ID_v2) {
        // The only case we can precisely predict the token data length
        tokenDataLen = minSize;
        tokenData = new byte[minSize];
        readFully(is, tokenData);
      } else {
        tokenDataLen = is.available();
        if (tokenDataLen >= minSize) { // read in one shot
          tokenData = new byte[tokenDataLen];
          readFully(is, tokenData);
        } else {
          byte[] tmp = new byte[minSize];
          readFully(is, tmp);
          // Hope while blocked in the read above, more data would
          // come and is.available() below contains the whole token.
          int more = is.available();
          tokenDataLen = minSize + more;
          tokenData = Arrays.copyOf(tmp, tokenDataLen);
          readFully(is, tokenData, minSize, more);
        }
      }

      if (tokenId == Krb5Token.WRAP_ID_v2) {
        rotate();
      }

      if (tokenId == Krb5Token.MIC_ID_v2
          || (tokenId == Krb5Token.WRAP_ID_v2 && !prop.getPrivacy())) {
        // Read checksum
        int chkLen = cipherHelper.getChecksumLength();
        checksum = new byte[chkLen];
        System.arraycopy(tokenData, tokenDataLen - chkLen, checksum, 0, chkLen);

        // validate EC for Wrap tokens without confidentiality
        if (tokenId == Krb5Token.WRAP_ID_v2 && !prop.getPrivacy()) {
          if (chkLen != ec) {
            throw new GSSException(
                GSSException.DEFECTIVE_TOKEN, -1, getTokenName(tokenId) + ":" + "EC incorrect!");
          }
        }
      }
    } catch (IOException e) {
      throw new GSSException(
          GSSException.DEFECTIVE_TOKEN, -1, getTokenName(tokenId) + ":" + e.getMessage());
    }
  }
示例#22
0
 private static Object[] fillNewTypedArray(
     Object[] example, Integer len, Object[] /*not ...*/ args) {
   Object[] a = Arrays.copyOf(example, len);
   fillWithArguments(a, 0, args);
   return a;
 }
示例#23
0
 byte[] getData() {
   return Arrays.copyOf(data, data.length);
 }
示例#24
0
 private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
   return Arrays.copyOf(a, a.length, arrayType);
 }
示例#25
0
 /**
  * Gets the valid offsets during this transition.
  *
  * <p>A gap will return an empty list, while an overlap will return both offsets.
  *
  * @return the list of valid offsets
  */
 List<ZoneOffset> getValidOffsets() {
   if (isGap()) {
     return Collections.emptyList();
   }
   return Arrays.asList(getOffsetBefore(), getOffsetAfter());
 }
示例#26
0
 static byte[] genPad(byte b, int count) {
   byte[] padding = new byte[count];
   Arrays.fill(padding, b);
   return padding;
 }