java.lang.invoke.MethodHandle.asType()方法的使用及代码示例

x33g5p2x  于2022-01-24 转载在 其他  
字(20.3k)|赞(0)|评价(0)|浏览(141)

本文整理了Java中java.lang.invoke.MethodHandle.asType()方法的一些代码示例,展示了MethodHandle.asType()的具体用法。这些代码示例主要来源于Github/Stackoverflow/Maven等平台,是从一些精选项目中提取出来的代码,具有较强的参考意义,能在一定程度帮忙到你。MethodHandle.asType()方法的具体详情如下:
包路径:java.lang.invoke.MethodHandle
类名称:MethodHandle
方法名:asType

MethodHandle.asType介绍

[英]Produces an adapter method handle which adapts the type of the current method handle to a new type. The resulting method handle is guaranteed to report a type which is equal to the desired new type.

If the original type and new type are equal, returns this.

The new method handle, when invoked, will perform the following steps:

  • Convert the incoming argument list to match the original method handle's argument list.
  • Invoke the original method handle on the converted argument list.
  • Convert any result returned by the original method handle to the return type of new method handle.

This method provides the crucial behavioral difference between #invokeExact and plain, inexact #invoke. The two methods perform the same steps when the caller's type descriptor exactly m atches the callee's, but when the types differ, plain #invokealso calls asType (or some internal equivalent) in order to match up the caller's and callee's types.

If the current method is a variable arity method handle argument list conversion may involve the conversion and collection of several arguments into an array, as #asVarargsCollector. In every other case, all conversions are applied pairwise, which means that each argument or return value is converted to exactly one argument or return value (or no return value). The applied conversions are defined by consulting the the corresponding component types of the old and new method handle types.

Let T0 and T1 be corresponding new and old parameter types, or old and new return types. Specifically, for some valid index i, let T0 =newType.parameterType(i) and T1 =this.type().parameterType(i). Or else, going the other way for return values, let T0 =this.type().returnType() and T1 =newType.returnType(). If the types are the same, the new method handle makes no change to the corresponding argument or return value (if any). Otherwise, one of the following conversions is applied if possible:

  • If T0 and T1 are references, then a cast to T1 is applied. (The types do not need to be related in any particular way. This is because a dynamic value of null can convert to any reference type.)
  • If T0 and T1 are primitives, then a Java method invocation conversion (JLS 5.3) is applied, if one exists. (Specifically, T0 must convert to T1 by a widening primitive conversion.)
  • If T0 is a primitive and T1 a reference, a Java casting conversion (JLS 5.5) is applied if one exists. (Specifically, the value is boxed from T0 to its wrapper class, which is then widened as needed to T1.)
  • If T0 is a reference and T1 a primitive, an unboxing conversion will be applied at runtime, possibly followed by a Java method invocation conversion (JLS 5.3) on the primitive value. (These are the primitive widening conversions.) T0 must be a wrapper class or a supertype of one. (In the case where T0 is Object, these are the conversions allowed by java.lang.reflect.Method#invoke.) The unboxing conversion must have a possibility of success, which means that if T0 is not itself a wrapper class, there must exist at least one wrapper class TW which is a subtype of T0 and whose unboxed primitive value can be widened to T1.
  • If the return type T1 is marked as void, any returned value is discarded
  • If the return type T0 is void and T1 a reference, a null value is introduced.
  • If the return type T0 is void and T1 a primitive, a zero value is introduced.
    (Note: Both T0 and T1 may be regarded as static types, because neither corresponds specifically to the dynamic type of any actual argument or return value.)

The method handle conversion cannot be made if any one of the required pairwise conversions cannot be made.

At runtime, the conversions applied to reference arguments or return values may require additional runtime checks which can fail. An unboxing operation may fail because the original reference is null, causing a java.lang.NullPointerException. An unboxing operation or a reference cast may also fail on a reference to an object of the wrong type, causing a java.lang.ClassCastException. Although an unboxing operation may accept several kinds of wrappers, if none are available, a ClassCastException will be thrown.
[中]生成适配器方法句柄,该句柄将当前方法句柄的类型调整为新类型。生成的方法句柄保证报告与所需新类型相等的类型。
如果原始类型和新类型相等,则返回该值。
调用新方法句柄时,将执行以下步骤:
转换传入参数列表以匹配原始方法句柄的参数列表。
调用转换参数列表上的原始方法句柄。
将原始方法句柄返回的任何结果转换为新方法句柄的返回类型。
这种方法提供了#invokeExact和简单、不精确的#invoke之间的关键行为差异。当调用者的类型描述符与被调用者的类型描述符完全匹配时,这两种方法执行相同的步骤,但当类型不同时,plain#invokealso调用asType(或一些内部等效的)以匹配调用者和被调用者的类型。
如果当前方法是变量arity方法,则句柄参数列表转换可能涉及将多个参数转换并收集到一个数组中,如#asVarargsCollector。在其他每种情况下,所有转换都应用为
成对
,这意味着每个参数或返回值都转换为一个参数或返回值(或无返回值)。应用的转换是通过参考新旧方法句柄类型的相应组件类型来定义的。
T0T1为对应的新旧参数类型,或新旧返回类型。具体来说,对于一些有效的索引i,让T0*=newType。参数类型(i)和T1=这个。类型()。参数类型(i)。或者,对于返回值,让T0=这个。类型()。returnType()和T1=newType。returnType()。如果类型相同,新方法句柄不会更改相应的参数或返回值(如果有)。否则,如果可能,将应用以下转换之一:
如果T0T1是引用,则应用对T1的转换。(类型不需要以任何特定方式关联。这是因为null的动态值可以转换为任何引用类型。)
如果T0
T1是原语,则应用Java方法调用转换(JLS 5.3)(如果存在)。(具体来说,T0必须通过加宽原语转换转换为T1。)
如果T0是一个原语,T1是一个引用,则应用Java转换(JLS 5.5)(如果存在)。(具体来说,该值从T0装箱到它的包装类,然后根据需要将包装类加宽到T1*)
如果T0是一个引用,T1是一个原语,那么将在运行时应用取消装箱转换,然后可能会对原语值进行Java方法调用转换(JLS 5.3)。(这些是基本的加宽转换。)T0必须是包装类或其超类型。(在T0为Object的情况下,这些是java.lang.reflect.Method#invoke允许的转换。)取消装箱转换必须有成功的可能性,这意味着如果T0本身不是包装类,则必须至少存在一个包装类TW*,它是T0的子类型,其取消装箱原语值可以扩展到T1
如果返回类型T1被标记为void,则任何返回值都将被丢弃
如果返回类型T0
为void,T1为引用,则引入空值。
如果返回类型T0为void,T1为原语,则引入零值。
注意:两个T0
T1都可以被视为静态类型,因为它们都不具体对应于任何实际参数或返回值的dynamic type*。)
如果无法进行任何所需的成对转换,则无法进行方法句柄转换。
在运行时,应用于引用参数或返回值的转换可能需要额外的运行时检查,这可能会失败。取消装箱操作可能会失败,因为原始引用为null,从而导致java错误。lang.NullPointerException。取消装箱操作或引用转换也可能会在对错误类型的对象的引用上失败,从而导致java错误。lang.ClassCastException。尽管拆箱操作可能会接受几种包装,但如果没有可用的包装,将抛出ClassCastException。

代码示例

代码示例来源:origin: org.apache.lucene/lucene-core

/**
 * Returns a correctly typed {@link MethodHandle} for the no-arg ctor of the given class.
 */
static final MethodHandle findAttributeImplCtor(Class<? extends AttributeImpl> clazz) {
 try {
  return lookup.findConstructor(clazz, NO_ARG_CTOR).asType(NO_ARG_RETURNING_ATTRIBUTEIMPL);
 } catch (NoSuchMethodException | IllegalAccessException e) {
  throw new IllegalArgumentException("Cannot lookup accessible no-arg constructor for: " + clazz.getName(), e);
 }
}

代码示例来源:origin: prestodb/presto

@Override
public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)
{
  List<Type> types = this.typeParameters.stream().map(boundVariables::getTypeVariable).collect(toImmutableList());
  List<ArgumentProperty> argumentProperties = nCopies(types.size(), valueTypeArgumentProperty(RETURN_NULL_ON_NULL));
  List<Class<?>> javaArgumentTypes = nCopies(types.size(), Block.class);
  MethodHandle methodHandle = METHOD_HANDLE.bindTo(types).asVarargsCollector(Block[].class).asType(methodType(Block.class, javaArgumentTypes));
  return new ScalarFunctionImplementation(false, argumentProperties, methodHandle, isDeterministic());
}

代码示例来源:origin: robolectric/robolectric

@SuppressWarnings("UnusedDeclaration")
public static CallSite bootstrapIntrinsic(MethodHandles.Lookup caller, String name,
  MethodType type, String callee) throws IllegalAccessException {
 MethodHandle mh = getMethodHandle(callee, name, type);
 if (mh == null) {
  throw new IllegalArgumentException("Could not find intrinsic for " + callee + ":" + name);
 }
 return new ConstantCallSite(mh.asType(type));
}

代码示例来源:origin: prestodb/presto

private ObjectStrategy(FunctionRegistry registry, Type type)
{
  hashCodeHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(HASH_CODE, ImmutableList.of(type)))
      .getMethodHandle()
      .asType(MethodType.methodType(long.class, Object.class));
  equalsHandle = registry.getScalarFunctionImplementation(registry.resolveOperator(EQUAL, ImmutableList.of(type, type)))
      .getMethodHandle()
      .asType(MethodType.methodType(Boolean.class, Object.class, Object.class));
}

代码示例来源:origin: apache/kafka

private static MethodHandle unmapJava7Or8(MethodHandles.Lookup lookup) throws ReflectiveOperationException {
  /* "Compile" a MethodHandle that is roughly equivalent to the following lambda:
   *
   * (ByteBuffer buffer) -> {
   *   sun.misc.Cleaner cleaner = ((java.nio.DirectByteBuffer) byteBuffer).cleaner();
   *   if (nonNull(cleaner))
   *     cleaner.clean();
   *   else
   *     noop(cleaner); // the noop is needed because MethodHandles#guardWithTest always needs both if and else
   * }
   */
  Class<?> directBufferClass = Class.forName("java.nio.DirectByteBuffer");
  Method m = directBufferClass.getMethod("cleaner");
  m.setAccessible(true);
  MethodHandle directBufferCleanerMethod = lookup.unreflect(m);
  Class<?> cleanerClass = directBufferCleanerMethod.type().returnType();
  MethodHandle cleanMethod = lookup.findVirtual(cleanerClass, "clean", methodType(void.class));
  MethodHandle nonNullTest = lookup.findStatic(MappedByteBuffers.class, "nonNull",
      methodType(boolean.class, Object.class)).asType(methodType(boolean.class, cleanerClass));
  MethodHandle noop = dropArguments(constant(Void.class, null).asType(methodType(void.class)), 0, cleanerClass);
  MethodHandle unmapper = filterReturnValue(directBufferCleanerMethod, guardWithTest(nonNullTest, cleanMethod, noop))
      .asType(methodType(void.class, ByteBuffer.class));
  return unmapper;
}

代码示例来源:origin: prestodb/presto

private Optional<MethodHandle> getConstructor(Method method, Optional<Constructor<?>> optionalConstructor)
{
  if (isStatic(method.getModifiers())) {
    return Optional.empty();
  }
  checkArgument(optionalConstructor.isPresent(), "Method [%s] is an instance method. It must be in a class annotated with @ScalarFunction, and the class is required to have a public constructor.", method);
  Constructor<?> constructor = optionalConstructor.get();
  Set<TypeParameter> constructorTypeParameters = Stream.of(constructor.getAnnotationsByType(TypeParameter.class))
      .collect(ImmutableSet.toImmutableSet());
  checkArgument(constructorTypeParameters.containsAll(typeParameters), "Method [%s] is an instance method and requires a public constructor containing all type parameters: %s", method, typeParameters);
  for (int i = 0; i < constructor.getParameterCount(); i++) {
    Annotation[] annotations = constructor.getParameterAnnotations()[i];
    checkArgument(containsImplementationDependencyAnnotation(annotations), "Constructors may only have meta parameters [%s]", constructor);
    checkArgument(annotations.length == 1, "Meta parameters may only have a single annotation [%s]", constructor);
    Annotation annotation = annotations[0];
    if (annotation instanceof TypeParameter) {
      checkTypeParameters(parseTypeSignature(((TypeParameter) annotation).value()), typeParameterNames, method);
    }
    constructorDependencies.add(createDependency(annotation, literalParameters));
  }
  MethodHandle result = constructorMethodHandle(FUNCTION_IMPLEMENTATION_ERROR, constructor);
  // Change type of return value to Object to make sure callers won't have classloader issues
  return Optional.of(result.asType(result.type().changeReturnType(Object.class)));
}

代码示例来源:origin: robolectric/robolectric

@Override public MethodHandle getMethodHandle(String methodName, MethodType type) throws NoSuchMethodException, IllegalAccessException {
  MethodHandle nothing = constant(Void.class, null).asType(methodType(void.class));
  if (type.parameterCount() != 0) {
   return dropArguments(nothing, 0, type.parameterArray());
  } else {
   return nothing;
  }
 }
}

代码示例来源:origin: org.codehaus.groovy/groovy

/**
 * Core method for indy method selection using runtime types.
 */
public static Object selectMethod(MutableCallSite callSite, Class sender, String methodName, int callID, Boolean safeNavigation, Boolean thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws Throwable {
  Selector selector = Selector.getSelector(callSite, sender, methodName, callID, safeNavigation, thisCall, spreadCall, arguments); 
  selector.setCallSiteTarget();
  MethodHandle call = selector.handle.asSpreader(Object[].class, arguments.length);
  call = call.asType(MethodType.methodType(Object.class,Object[].class));
  return call.invokeExact(arguments);
}

代码示例来源:origin: org.codehaus.groovy/groovy

/**
 * Sets a handle to call {@link GroovyInterceptable#invokeMethod(String, Object)}
 */
public boolean setInterceptor() {
  if (!(this.args[0] instanceof GroovyInterceptable)) return false;
  handle = MethodHandles.insertArguments(INTERCEPTABLE_INVOKER, 1, this.name);
  handle = handle.asCollector(Object[].class, targetType.parameterCount()-1); 
  handle = handle.asType(targetType);
  return true;
}

代码示例来源:origin: prestodb/presto

@Override
public ScalarFunctionImplementation specialize(
    BoundVariables boundVariables, int arity, TypeManager typeManager,
    FunctionRegistry functionRegistry)
{
  Type toType = boundVariables.getTypeVariable("E");
  MethodHandle methodHandle = METHOD_HANDLE_NON_NULL.asType(METHOD_HANDLE_NON_NULL.type().changeReturnType(toType.getJavaType()));
  return new ScalarFunctionImplementation(
      false,
      ImmutableList.of(valueTypeArgumentProperty(RETURN_NULL_ON_NULL)),
      methodHandle,
      isDeterministic());
}

代码示例来源:origin: prestodb/presto

private MethodHandle getMethodHandle(Method method)
{
  MethodHandle methodHandle = methodHandle(FUNCTION_IMPLEMENTATION_ERROR, method);
  if (!isStatic(method.getModifiers())) {
    // Change type of "this" argument to Object to make sure callers won't have classloader issues
    methodHandle = methodHandle.asType(methodHandle.type().changeParameterType(0, Object.class));
    // Re-arrange the parameters, so that the "this" parameter is after the meta parameters
    int[] permutedIndices = new int[methodHandle.type().parameterCount()];
    permutedIndices[0] = dependencies.size();
    MethodType newType = methodHandle.type().changeParameterType(dependencies.size(), methodHandle.type().parameterType(0));
    for (int i = 0; i < dependencies.size(); i++) {
      permutedIndices[i + 1] = i;
      newType = newType.changeParameterType(i, methodHandle.type().parameterType(i + 1));
    }
    for (int i = dependencies.size() + 1; i < permutedIndices.length; i++) {
      permutedIndices[i] = i;
    }
    methodHandle = permuteArguments(methodHandle, newType, permutedIndices);
  }
  return methodHandle;
}

代码示例来源:origin: prestodb/presto

@Override
public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)
{
  Type returnType = boundVariables.getTypeVariable("T");
  return new ScalarFunctionImplementation(
      true,
      ImmutableList.of(functionTypeArgumentProperty(InvokeLambda.class)),
      METHOD_HANDLE.asType(
          METHOD_HANDLE.type()
              .changeReturnType(wrap(returnType.getJavaType()))),
      isDeterministic());
}

代码示例来源:origin: robolectric/robolectric

private static MethodHandle cleanStackTraces(MethodHandle mh) {
  MethodType type = EXCEPTION_HANDLER.type().changeReturnType(mh.type().returnType());
  return catchException(mh, Throwable.class, EXCEPTION_HANDLER.asType(type));
 }
}

代码示例来源:origin: robolectric/robolectric

@Override public MethodHandle getShadowCreator(Class<?> theClass) {
 ShadowInfo shadowInfo = getShadowInfo(theClass);
 if (shadowInfo == null) return dropArguments(NO_SHADOW_HANDLE, 0, theClass);
 String shadowClassName = shadowInfo.shadowClassName;
 try {
  Class<?> shadowClass = Class.forName(shadowClassName, false, theClass.getClassLoader());
  ShadowMetadata shadowMetadata = getShadowMetadata(shadowClass);
  MethodHandle mh = identity(shadowClass); // (instance)
  mh = dropArguments(mh, 1, theClass); // (instance)
  for (Field field : shadowMetadata.realObjectFields) {
   MethodHandle setter = LOOKUP.unreflectSetter(field);
   MethodType setterType = mh.type().changeReturnType(void.class);
   mh = foldArguments(mh, setter.asType(setterType));
  }
  mh = foldArguments(mh, LOOKUP.unreflectConstructor(shadowMetadata.constructor));  // (shadow, instance)
  return mh; // (instance)
 } catch (IllegalAccessException | ClassNotFoundException e) {
  throw new RuntimeException("Could not instantiate shadow " + shadowClassName + " for " + theClass, e);
 }
}

代码示例来源:origin: prestodb/presto

private static BlockBuilder createMapBuilder(int expectedEntries)
{
  MethodHandle varcharNativeEquals = MethodHandleUtil.methodHandle(Slice.class, "equals", Object.class).asType(MethodType.methodType(boolean.class, Slice.class, Slice.class));
  MethodHandle varcharBlockNativeEquals = compose(varcharNativeEquals, nativeValueGetter(VARCHAR));
  MethodHandle varcharBlockEquals = compose(varcharNativeEquals, nativeValueGetter(VARCHAR), nativeValueGetter(VARCHAR));
  return new MapBlockBuilder(
      VARCHAR,
      VARCHAR,
      varcharBlockNativeEquals,
      varcharBlockEquals,
      MethodHandleUtil.methodHandle(Slice.class, "hashCode").asType(MethodType.methodType(long.class, Slice.class)),
      MethodHandleUtil.methodHandle(TestColumnarMap.class, "blockVarcharHashCode", Block.class, int.class),
      null,
      expectedEntries);
}

代码示例来源:origin: prestodb/presto

@Override
  public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)
  {
    Type fromType = boundVariables.getTypeVariable("F");
    Type toType = boundVariables.getTypeVariable("T");

    Class<?> returnType = Primitives.wrap(toType.getJavaType());
    List<ArgumentProperty> argumentProperties;
    MethodHandle tryCastHandle;

    // the resulting method needs to return a boxed type
    Signature signature = functionRegistry.getCoercion(fromType, toType);
    ScalarFunctionImplementation implementation = functionRegistry.getScalarFunctionImplementation(signature);
    argumentProperties = ImmutableList.of(implementation.getArgumentProperty(0));
    MethodHandle coercion = implementation.getMethodHandle();
    coercion = coercion.asType(methodType(returnType, coercion.type()));

    MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class);
    tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler);

    return new ScalarFunctionImplementation(true, argumentProperties, tryCastHandle, isDeterministic());
  }
}

代码示例来源:origin: robolectric/robolectric

private static MethodHandle bindWithFallback(RoboCallSite site, MethodHandle mh,
  MethodHandle fallback) {
 SwitchPoint switchPoint = getInvalidator(site.getTheClass());
 MethodType type = site.type();
 MethodHandle boundFallback = foldArguments(exactInvoker(type), fallback.bindTo(site));
 try {
  mh = switchPoint.guardWithTest(mh.asType(type), boundFallback);
 } catch (WrongMethodTypeException e) {
  if (site instanceof MethodCallSite) {
   MethodCallSite methodCallSite = (MethodCallSite) site;
   throw new RuntimeException("failed to bind " + methodCallSite.thisType() + "."
     + methodCallSite.getName(), e);
  } else {
   throw e;
  }
 }
 site.setTarget(mh);
 return mh;
}

代码示例来源:origin: prestodb/presto

@Override
public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)
{
  Type argumentType = boundVariables.getTypeVariable("T");
  Type returnType = boundVariables.getTypeVariable("U");
  return new ScalarFunctionImplementation(
      true,
      ImmutableList.of(
          valueTypeArgumentProperty(USE_BOXED_TYPE),
          functionTypeArgumentProperty(UnaryFunctionInterface.class)),
      METHOD_HANDLE.asType(
          METHOD_HANDLE.type()
              .changeReturnType(wrap(returnType.getJavaType()))
              .changeParameterType(0, wrap(argumentType.getJavaType()))),
      isDeterministic());
}

代码示例来源:origin: prestodb/presto

@Override
public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry)
{
  Type inputType = boundVariables.getTypeVariable("T");
  Type intermediateType = boundVariables.getTypeVariable("S");
  Type outputType = boundVariables.getTypeVariable("R");
  MethodHandle methodHandle = METHOD_HANDLE.bindTo(inputType);
  return new ScalarFunctionImplementation(
      true,
      ImmutableList.of(
          valueTypeArgumentProperty(RETURN_NULL_ON_NULL),
          valueTypeArgumentProperty(USE_BOXED_TYPE),
          functionTypeArgumentProperty(BinaryFunctionInterface.class),
          functionTypeArgumentProperty(UnaryFunctionInterface.class)),
      methodHandle.asType(
          methodHandle.type()
              .changeParameterType(1, Primitives.wrap(intermediateType.getJavaType()))
              .changeReturnType(Primitives.wrap(outputType.getJavaType()))),
      isDeterministic());
}

代码示例来源:origin: prestodb/presto

/**
 * The signature of the returned MethodHandle is (Block fromMap, int position, ConnectorSession session, BlockBuilder mapBlockBuilder)void.
 * The processor will get the value from fromMap, cast it and write to toBlock.
 */
private MethodHandle buildProcessor(FunctionRegistry functionRegistry, Type fromType, Type toType, boolean isKey)
{
  MethodHandle getter = nativeValueGetter(fromType);
  // Adapt cast that takes ([ConnectorSession,] ?) to one that takes (?, ConnectorSession), where ? is the return type of getter.
  ScalarFunctionImplementation castImplementation = functionRegistry.getScalarFunctionImplementation(functionRegistry.getCoercion(fromType, toType));
  MethodHandle cast = castImplementation.getMethodHandle();
  if (cast.type().parameterArray()[0] != ConnectorSession.class) {
    cast = MethodHandles.dropArguments(cast, 0, ConnectorSession.class);
  }
  cast = permuteArguments(cast, methodType(cast.type().returnType(), cast.type().parameterArray()[1], cast.type().parameterArray()[0]), 1, 0);
  MethodHandle target = compose(cast, getter);
  // If the key cast function is nullable, check the result is not null.
  if (isKey && castImplementation.isNullable()) {
    target = compose(nullChecker(target.type().returnType()), target);
  }
  MethodHandle writer = nativeValueWriter(toType);
  writer = permuteArguments(writer, methodType(void.class, writer.type().parameterArray()[1], writer.type().parameterArray()[0]), 1, 0);
  return compose(writer, target.asType(methodType(unwrap(target.type().returnType()), target.type().parameterArray())));
}

相关文章