private readonly String LambdaClassName; // Generated name for the generated class "X$$Lambda$1" /// <summary> /// General meta-factory constructor, supporting both standard cases and /// allowing for uncommon options such as serialization or bridging. /// </summary> /// <param name="caller"> Stacked automatically by VM; represents a lookup context /// with the accessibility privileges of the caller. </param> /// <param name="invokedType"> Stacked automatically by VM; the signature of the /// invoked method, which includes the expected static /// type of the returned lambda object, and the static /// types of the captured arguments for the lambda. In /// the event that the implementation method is an /// instance method, the first argument in the invocation /// signature will correspond to the receiver. </param> /// <param name="samMethodName"> Name of the method in the functional interface to /// which the lambda or method reference is being /// converted, represented as a String. </param> /// <param name="samMethodType"> Type of the method in the functional interface to /// which the lambda or method reference is being /// converted, represented as a MethodType. </param> /// <param name="implMethod"> The implementation method which should be called (with /// suitable adaptation of argument types, return types, /// and adjustment for captured arguments) when methods of /// the resulting functional interface instance are invoked. </param> /// <param name="instantiatedMethodType"> The signature of the primary functional /// interface method after type variables are /// substituted with their instantiation from /// the capture site </param> /// <param name="isSerializable"> Should the lambda be made serializable? If set, /// either the target type or one of the additional SAM /// types must extend {@code Serializable}. </param> /// <param name="markerInterfaces"> Additional interfaces which the lambda object /// should implement. </param> /// <param name="additionalBridges"> Method types for additional signatures to be /// bridged to the implementation method </param> /// <exception cref="LambdaConversionException"> If any of the meta-factory protocol /// invariants are violated </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, String samMethodName, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, boolean isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) throws LambdaConversionException public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, MethodType invokedType, String samMethodName, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType, bool isSerializable, Class[] markerInterfaces, MethodType[] additionalBridges) : base(caller, invokedType, samMethodName, samMethodType, implMethod, instantiatedMethodType, isSerializable, markerInterfaces, additionalBridges) { ImplMethodClassName = ImplDefiningClass.Name.Replace('.', '/'); ImplMethodName = ImplInfo.Name; ImplMethodDesc = ImplMethodType.ToMethodDescriptorString(); ImplMethodReturnClass = (ImplKind == MethodHandleInfo.REF_newInvokeSpecial) ? ImplDefiningClass : ImplMethodType.ReturnType(); ConstructorType = invokedType.ChangeReturnType(Void.TYPE); LambdaClassName = TargetClass.Name.Replace('.', '/') + "$$Lambda$" + Counter.IncrementAndGet(); Cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.ParameterCount(); if (parameterCount > 0) { ArgNames = new String[parameterCount]; ArgDescs = new String[parameterCount]; for (int i = 0; i < parameterCount; i++) { ArgNames[i] = "arg$" + (i + 1); ArgDescs[i] = BytecodeDescriptor.unparse(invokedType.ParameterType(i)); } } else { ArgNames = ArgDescs = EMPTY_STRING_ARRAY; } }
internal virtual LambdaForm CollectArgumentsForm(int pos, MethodType collectorType) { int collectorArity = collectorType.ParameterCount(); bool dropResult = (collectorType.ReturnType() == typeof(void)); if (collectorArity == 1 && !dropResult) { return(FilterArgumentForm(pos, basicType(collectorType.ParameterType(0)))); } BasicType[] newTypes = BasicType.basicTypes(collectorType.ParameterList()); Transform.Kind kind = (dropResult ? Transform.Kind.COLLECT_ARGS_TO_VOID : Transform.Kind.COLLECT_ARGS); if (dropResult && collectorArity == 0) // pure side effect { pos = 1; } Transform key = Transform.Of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes)); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed - (dropResult ? 0 : 1) + collectorArity); return(form); } form = MakeArgumentCombinationForm(pos, collectorType, false, dropResult); return(PutInCache(key, form)); }
/// <summary> /// Create a LF which simply reinvokes a target of the given basic type. </summary> internal static LambdaForm MakeReinvokerForm(MethodHandle target, int whichCache, Object constraint, String debugString, bool forceInline, NamedFunction getTargetFn, NamedFunction preActionFn) { MethodType mtype = target.Type().BasicType(); bool customized = (whichCache <0 || mtype.ParameterSlotCount()> MethodType.MAX_MH_INVOKER_ARITY); bool hasPreAction = (preActionFn != null); LambdaForm form; if (!customized) { form = mtype.Form().CachedLambdaForm(whichCache); if (form != null) { return(form); } } const int THIS_DMH = 0; const int ARG_BASE = 1; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); int ARG_LIMIT = ARG_BASE + mtype.ParameterCount(); int nameCursor = ARG_LIMIT; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int PRE_ACTION = hasPreAction ? nameCursor++ : -1; int PRE_ACTION = hasPreAction ? nameCursor++: -1; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int NEXT_MH = customized ? -1 : nameCursor++; int NEXT_MH = customized ? -1 : nameCursor++; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int REINVOKE = nameCursor++; int REINVOKE = nameCursor++; LambdaForm.Name[] names = LambdaForm.Arguments(nameCursor - ARG_LIMIT, mtype.InvokerType()); assert(names.Length == nameCursor); names[THIS_DMH] = names[THIS_DMH].WithConstraint(constraint); Object[] targetArgs; if (hasPreAction) { names[PRE_ACTION] = new LambdaForm.Name(preActionFn, names[THIS_DMH]); } if (customized) { targetArgs = Arrays.CopyOfRange(names, ARG_BASE, ARG_LIMIT, typeof(Object[])); names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself } else { names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]); targetArgs = Arrays.CopyOfRange(names, THIS_DMH, ARG_LIMIT, typeof(Object[])); targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs); } form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline); if (!customized) { form = mtype.Form().SetCachedLambdaForm(whichCache, form); } return(form); }
private static MethodHandle BindCaller(MethodHandle target, Class hostClass) { MethodHandle cbmh = MethodHandleImpl.BindCaller(target, hostClass); if (target.VarargsCollector) { MethodType type = cbmh.Type(); int arity = type.ParameterCount(); return(cbmh.AsVarargsCollector(type.ParameterType(arity - 1))); } return(cbmh); }
internal virtual LambdaForm FoldArgumentsForm(int foldPos, bool dropResult, MethodType combinerType) { int combinerArity = combinerType.ParameterCount(); Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS); Transform key = Transform.Of(kind, foldPos, combinerArity); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0)); return(form); } form = MakeArgumentCombinationForm(foldPos, combinerType, true, dropResult); return(PutInCache(key, form)); }
private static LambdaForm MakePreparedLambdaForm(MethodType mtype, int which) { bool needsInit = (which == LF_INVSTATIC_INIT); bool doesAlloc = (which == LF_NEWINVSPECIAL); String linkerName, lambdaName; switch (which) { case LF_INVVIRTUAL: linkerName = "linkToVirtual"; lambdaName = "DMH.invokeVirtual"; break; case LF_INVSTATIC: linkerName = "linkToStatic"; lambdaName = "DMH.invokeStatic"; break; case LF_INVSTATIC_INIT: linkerName = "linkToStatic"; lambdaName = "DMH.invokeStaticInit"; break; case LF_INVSPECIAL: linkerName = "linkToSpecial"; lambdaName = "DMH.invokeSpecial"; break; case LF_INVINTERFACE: linkerName = "linkToInterface"; lambdaName = "DMH.invokeInterface"; break; case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; lambdaName = "DMH.newInvokeSpecial"; break; default: throw new InternalError("which=" + which); } MethodType mtypeWithArg = mtype.AppendParameterTypes(typeof(MemberName)); if (doesAlloc) { mtypeWithArg = mtypeWithArg.InsertParameterTypes(0, typeof(Object)).ChangeReturnType(typeof(void)); // <init> returns void - insert newly allocated obj } MemberName linker = new MemberName(typeof(MethodHandle), linkerName, mtypeWithArg, REF_invokeStatic); try { linker = IMPL_NAMES.ResolveOrFail(REF_invokeStatic, linker, null, typeof(NoSuchMethodException)); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } const int DMH_THIS = 0; const int ARG_BASE = 1; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); int ARG_LIMIT = ARG_BASE + mtype.ParameterCount(); int nameCursor = ARG_LIMIT; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1); int NEW_OBJ = (doesAlloc ? nameCursor++: -1); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int GET_MEMBER = nameCursor++; int GET_MEMBER = nameCursor++; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int LINKER_CALL = nameCursor++; int LINKER_CALL = nameCursor++; Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.InvokerType()); assert(names.Length == nameCursor); if (doesAlloc) { // names = { argx,y,z,... new C, init method } names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]); names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]); } else if (needsInit) { names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]); } else { names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]); } assert(FindDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]); Object[] outArgs = Arrays.CopyOfRange(names, ARG_BASE, GET_MEMBER + 1, typeof(Object[])); assert(outArgs[outArgs.Length - 1] == names[GET_MEMBER]); // look, shifted args! int result = LAST_RESULT; if (doesAlloc) { assert(outArgs[outArgs.Length - 2] == names[NEW_OBJ]); // got to move this one System.Array.Copy(outArgs, 0, outArgs, 1, outArgs.Length - 2); outArgs[0] = names[NEW_OBJ]; result = NEW_OBJ; } names[LINKER_CALL] = new Name(linker, outArgs); lambdaName += "_" + shortenSignature(basicTypeSignature(mtype)); LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result); // This is a tricky bit of code. Don't send it through the LF interpreter. lform.CompileToBytecode(); return(lform); }
private LambdaForm MakeArgumentCombinationForm(int pos, MethodType combinerType, bool keepArguments, bool dropResult) { LambdaFormBuffer buf = Buffer(); buf.StartEdit(); int combinerArity = combinerType.ParameterCount(); int resultArity = (dropResult ? 0 : 1); assert(pos <= MethodType.MAX_JVM_ARITY); assert(pos + resultArity + (keepArguments ? combinerArity : 0) <= LambdaForm.Arity_Renamed); assert(pos > 0); // cannot filter the MH arg itself assert(combinerType == combinerType.BasicType()); assert(combinerType.ReturnType() != typeof(void) || dropResult); BoundMethodHandle.SpeciesData oldData = OldSpeciesData(); BoundMethodHandle.SpeciesData newData = NewSpeciesData(L_TYPE); // The newly created LF will run with a different BMH. // Switch over any pre-existing BMH field references to the new BMH class. Name oldBaseAddress = LambdaForm.Parameter(0); // BMH holding the values buf.ReplaceFunctions(oldData.GetterFunctions(), newData.GetterFunctions(), oldBaseAddress); Name newBaseAddress = oldBaseAddress.withConstraint(newData); buf.RenameParameter(0, newBaseAddress); Name getCombiner = new Name(newData.GetterFunction(oldData.FieldCount()), newBaseAddress); Object[] combinerArgs = new Object[1 + combinerArity]; combinerArgs[0] = getCombiner; Name[] newParams; if (keepArguments) { newParams = new Name[0]; System.Array.Copy(LambdaForm.Names, pos + resultArity, combinerArgs, 1, combinerArity); } else { newParams = new Name[combinerArity]; BasicType[] newTypes = basicTypes(combinerType.ParameterList()); for (int i = 0; i < newTypes.Length; i++) { newParams[i] = new Name(pos + i, newTypes[i]); } System.Array.Copy(newParams, 0, combinerArgs, 1, combinerArity); } Name callCombiner = new Name(combinerType, combinerArgs); // insert the two new expressions int exprPos = LambdaForm.Arity(); buf.InsertExpression(exprPos + 0, getCombiner); buf.InsertExpression(exprPos + 1, callCombiner); // insert new arguments, if needed int argPos = pos + resultArity; // skip result parameter foreach (Name newParam in newParams) { buf.InsertParameter(argPos++, newParam); } assert(buf.LastIndexOf(callCombiner) == exprPos + 1 + newParams.Length); if (!dropResult) { buf.ReplaceParameterByCopy(pos, exprPos + 1 + newParams.Length); } return(buf.EndEdit()); }
internal virtual LambdaForm CollectArgumentArrayForm(int pos, MethodHandle arrayCollector) { MethodType collectorType = arrayCollector.Type(); int collectorArity = collectorType.ParameterCount(); assert(arrayCollector.IntrinsicName() == Intrinsic.NEW_ARRAY); Class arrayType = collectorType.ReturnType(); Class elementType = arrayType.ComponentType; BasicType argType = basicType(elementType); int argTypeKey = argType.ordinal(); if (argType.basicTypeClass() != elementType) { // return null if it requires more metadata (like String[].class) if (!elementType.Primitive) { return(null); } argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); } assert(collectorType.ParameterList().Equals(Collections.NCopies(collectorArity, elementType))); Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY; Transform key = Transform.Of(kind, pos, collectorArity, argTypeKey); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed - 1 + collectorArity); return(form); } LambdaFormBuffer buf = Buffer(); buf.StartEdit(); assert(pos + 1 <= LambdaForm.Arity_Renamed); assert(pos > 0); // cannot filter the MH arg itself Name[] newParams = new Name[collectorArity]; for (int i = 0; i < collectorArity; i++) { newParams[i] = new Name(pos + i, argType); } Name callCombiner = new Name(arrayCollector, (Object[])newParams); //... // insert the new expression int exprPos = LambdaForm.Arity(); buf.InsertExpression(exprPos, callCombiner); // insert new arguments int argPos = pos + 1; // skip result parameter foreach (Name newParam in newParams) { buf.InsertParameter(argPos++, newParam); } assert(buf.LastIndexOf(callCombiner) == exprPos + newParams.Length); buf.ReplaceParameterByCopy(pos, exprPos + newParams.Length); form = buf.EndEdit(); return(PutInCache(key, form)); }
/// <summary> /// Produces an instance of the given single-method interface which redirects /// its calls to the given method handle. /// <para> /// A single-method interface is an interface which declares a uniquely named method. /// When determining the uniquely named method of a single-method interface, /// the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode}) /// are disregarded. For example, <seealso cref="java.util.Comparator"/> is a single-method interface, /// even though it re-declares the {@code Object.equals} method. /// </para> /// <para> /// The interface must be public. No additional access checks are performed. /// </para> /// <para> /// The resulting instance of the required type will respond to /// invocation of the type's uniquely named method by calling /// the given target on the incoming arguments, /// and returning or throwing whatever the target /// returns or throws. The invocation will be as if by /// {@code target.invoke}. /// The target's type will be checked before the /// instance is created, as if by a call to {@code asType}, /// which may result in a {@code WrongMethodTypeException}. /// </para> /// <para> /// The uniquely named method is allowed to be multiply declared, /// with distinct type descriptors. (E.g., it can be overloaded, /// or can possess bridge methods.) All such declarations are /// connected directly to the target method handle. /// Argument and return types are adjusted by {@code asType} /// for each individual declaration. /// </para> /// <para> /// The wrapper instance will implement the requested interface /// and its super-types, but no other single-method interfaces. /// This means that the instance will not unexpectedly /// pass an {@code instanceof} test for any unrequested type. /// <p style="font-size:smaller;"> /// <em>Implementation Note:</em> /// Therefore, each instance must implement a unique single-method interface. /// Implementations may not bundle together /// multiple single-method interfaces onto single implementation classes /// in the style of <seealso cref="java.awt.AWTEventMulticaster"/>. /// </para> /// <para> /// The method handle may throw an <em>undeclared exception</em>, /// which means any checked exception (or other checked throwable) /// not declared by the requested type's single abstract method. /// If this happens, the throwable will be wrapped in an instance of /// <seealso cref="java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException"/> /// and thrown in that wrapped form. /// </para> /// <para> /// Like <seealso cref="java.lang.Integer#valueOf Integer.valueOf"/>, /// {@code asInterfaceInstance} is a factory method whose results are defined /// by their behavior. /// It is not guaranteed to return a new instance for every call. /// </para> /// <para> /// Because of the possibility of <seealso cref="java.lang.reflect.Method#isBridge bridge methods"/> /// and other corner cases, the interface may also have several abstract methods /// with the same name but having distinct descriptors (types of returns and parameters). /// In this case, all the methods are bound in common to the one given target. /// The type check and effective {@code asType} conversion is applied to each /// method type descriptor, and all abstract methods are bound to the target in common. /// Beyond this type check, no further checks are made to determine that the /// abstract methods are related in any way. /// </para> /// <para> /// Future versions of this API may accept additional types, /// such as abstract classes with single abstract methods. /// Future versions of this API may also equip wrapper instances /// with one or more additional public "marker" interfaces. /// </para> /// <para> /// If a security manager is installed, this method is caller sensitive. /// During any invocation of the target method handle via the returned wrapper, /// the original creator of the wrapper (the caller) will be visible /// to context checks requested by the security manager. /// /// </para> /// </summary> /// @param <T> the desired type of the wrapper, a single-method interface </param> /// <param name="intfc"> a class object representing {@code T} </param> /// <param name="target"> the method handle to invoke from the wrapper </param> /// <returns> a correctly-typed wrapper for the given target </returns> /// <exception cref="NullPointerException"> if either argument is null </exception> /// <exception cref="IllegalArgumentException"> if the {@code intfc} is not a /// valid argument to this method </exception> /// <exception cref="WrongMethodTypeException"> if the target cannot /// be converted to the type required by the requested interface </exception> // Other notes to implementors: // <p> // No stable mapping is promised between the single-method interface and // the implementation class C. Over time, several implementation // classes might be used for the same type. // <p> // If the implementation is able // to prove that a wrapper of the required type // has already been created for a given // method handle, or for another method handle with the // same behavior, the implementation may return that wrapper in place of // a new wrapper. // <p> // This method is designed to apply to common use cases // where a single method handle must interoperate with // an interface that implements a function-like // API. Additional variations, such as single-abstract-method classes with // private constructors, or interfaces with multiple but related // entry points, must be covered by hand-written or automatically // generated adapter classes. // //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @CallerSensitive public static <T> T asInterfaceInstance(final Class intfc, final MethodHandle target) //JAVA TO C# CONVERTER WARNING: 'final' parameters are not allowed in .NET: public static T asInterfaceInstance <T>(Class intfc, MethodHandle target) { if (!intfc.Interface || !Modifier.IsPublic(intfc.Modifiers)) { throw newIllegalArgumentException("not a public interface", intfc.Name); } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final MethodHandle mh; MethodHandle mh; if (System.SecurityManager != null) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final Class caller = sun.reflect.Reflection.getCallerClass(); Class caller = Reflection.CallerClass; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; ClassLoader ccl = caller != null ? caller.ClassLoader : null; ReflectUtil.checkProxyPackageAccess(ccl, intfc); mh = ccl != null?BindCaller(target, caller) : target; } else { mh = target; } ClassLoader proxyLoader = intfc.ClassLoader; if (proxyLoader == null) { ClassLoader cl = Thread.CurrentThread.ContextClassLoader; // avoid use of BCP proxyLoader = cl != null ? cl : ClassLoader.SystemClassLoader; } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final Method[] methods = getSingleNameMethods(intfc); Method[] methods = GetSingleNameMethods(intfc); if (methods == null) { throw newIllegalArgumentException("not a single-method interface", intfc.Name); } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final MethodHandle[] vaTargets = new MethodHandle[methods.length]; MethodHandle[] vaTargets = new MethodHandle[methods.Length]; for (int i = 0; i < methods.Length; i++) { Method sm = methods[i]; MethodType smMT = MethodType.MethodType(sm.ReturnType, sm.ParameterTypes); MethodHandle checkTarget = mh.AsType(smMT); // make throw WMT checkTarget = checkTarget.AsType(checkTarget.Type().ChangeReturnType(typeof(Object))); vaTargets[i] = checkTarget.AsSpreader(typeof(Object[]), smMT.ParameterCount()); } //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final InvocationHandler ih = new InvocationHandler() InvocationHandler ih = new InvocationHandlerAnonymousInnerClassHelper(intfc, target, methods, vaTargets); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final Object proxy; Object proxy; if (System.SecurityManager != null) { // sun.invoke.WrapperInstance is a restricted interface not accessible // by any non-null class loader. //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final ClassLoader loader = proxyLoader; ClassLoader loader = proxyLoader; proxy = AccessController.doPrivileged(new PrivilegedActionAnonymousInnerClassHelper(intfc, ih, loader)); } else { proxy = Proxy.NewProxyInstance(proxyLoader, new Class[] { intfc, typeof(WrapperInstance) }, ih); } return(intfc.Cast(proxy)); }
/// <summary> /// Check the meta-factory arguments for errors </summary> /// <exception cref="LambdaConversionException"> if there are improper conversions </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: void validateMetafactoryArgs() throws LambdaConversionException internal virtual void ValidateMetafactoryArgs() { switch (ImplKind) { case MethodHandleInfo.REF_invokeInterface: case MethodHandleInfo.REF_invokeVirtual: case MethodHandleInfo.REF_invokeStatic: case MethodHandleInfo.REF_newInvokeSpecial: case MethodHandleInfo.REF_invokeSpecial: break; default: throw new LambdaConversionException(string.Format("Unsupported MethodHandle kind: {0}", ImplInfo)); } // Check arity: optional-receiver + captured + SAM == impl //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int implArity = implMethodType.parameterCount(); int implArity = ImplMethodType.ParameterCount(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int receiverArity = implIsInstanceMethod ? 1 : 0; int receiverArity = ImplIsInstanceMethod ? 1 : 0; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int capturedArity = invokedType.parameterCount(); int capturedArity = InvokedType.ParameterCount(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int samArity = samMethodType.parameterCount(); int samArity = SamMethodType.ParameterCount(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int instantiatedArity = instantiatedMethodType.parameterCount(); int instantiatedArity = InstantiatedMethodType.ParameterCount(); if (implArity + receiverArity != capturedArity + samArity) { throw new LambdaConversionException(string.Format("Incorrect number of parameters for {0} method {1}; {2:D} captured parameters, {3:D} functional interface method parameters, {4:D} implementation parameters", ImplIsInstanceMethod ? "instance" : "static", ImplInfo, capturedArity, samArity, implArity)); } if (instantiatedArity != samArity) { throw new LambdaConversionException(string.Format("Incorrect number of parameters for {0} method {1}; {2:D} instantiated parameters, {3:D} functional interface method parameters", ImplIsInstanceMethod ? "instance" : "static", ImplInfo, instantiatedArity, samArity)); } foreach (MethodType bridgeMT in AdditionalBridges) { if (bridgeMT.ParameterCount() != samArity) { throw new LambdaConversionException(string.Format("Incorrect number of parameters for bridge signature {0}; incompatible with {1}", bridgeMT, SamMethodType)); } } // If instance: first captured arg (receiver) must be subtype of class where impl method is defined //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int capturedStart; int capturedStart; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int samStart; int samStart; if (ImplIsInstanceMethod) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final Class receiverClass; Class receiverClass; // implementation is an instance method, adjust for receiver in captured variables / SAM arguments if (capturedArity == 0) { // receiver is function parameter capturedStart = 0; samStart = 1; receiverClass = InstantiatedMethodType.ParameterType(0); } else { // receiver is a captured variable capturedStart = 1; samStart = 0; receiverClass = InvokedType.ParameterType(0); } // check receiver type if (!receiverClass.IsSubclassOf(ImplDefiningClass)) { throw new LambdaConversionException(string.Format("Invalid receiver type {0}; not a subtype of implementation type {1}", receiverClass, ImplDefiningClass)); } Class implReceiverClass = ImplMethod.Type().ParameterType(0); if (implReceiverClass != ImplDefiningClass && !receiverClass.IsSubclassOf(implReceiverClass)) { throw new LambdaConversionException(string.Format("Invalid receiver type {0}; not a subtype of implementation receiver type {1}", receiverClass, implReceiverClass)); } } else { // no receiver capturedStart = 0; samStart = 0; } // Check for exact match on non-receiver captured arguments //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int implFromCaptured = capturedArity - capturedStart; int implFromCaptured = capturedArity - capturedStart; for (int i = 0; i < implFromCaptured; i++) { Class implParamType = ImplMethodType.ParameterType(i); Class capturedParamType = InvokedType.ParameterType(i + capturedStart); if (!capturedParamType.Equals(implParamType)) { throw new LambdaConversionException(string.Format("Type mismatch in captured lambda parameter {0:D}: expecting {1}, found {2}", i, capturedParamType, implParamType)); } } // Check for adaptation match on SAM arguments //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int samOffset = samStart - implFromCaptured; int samOffset = samStart - implFromCaptured; for (int i = implFromCaptured; i < implArity; i++) { Class implParamType = ImplMethodType.ParameterType(i); Class instantiatedParamType = InstantiatedMethodType.ParameterType(i + samOffset); if (!IsAdaptableTo(instantiatedParamType, implParamType, true)) { throw new LambdaConversionException(string.Format("Type mismatch for lambda argument {0:D}: {1} is not convertible to {2}", i, instantiatedParamType, implParamType)); } } // Adaptation match: return type Class expectedType = InstantiatedMethodType.ReturnType(); Class actualReturnType = (ImplKind == MethodHandleInfo.REF_newInvokeSpecial) ? ImplDefiningClass : ImplMethodType.ReturnType(); Class samReturnType = SamMethodType.ReturnType(); if (!IsAdaptableToAsReturn(actualReturnType, expectedType)) { throw new LambdaConversionException(string.Format("Type mismatch for lambda return: {0} is not convertible to {1}", actualReturnType, expectedType)); } if (!IsAdaptableToAsReturnStrict(expectedType, samReturnType)) { throw new LambdaConversionException(string.Format("Type mismatch for lambda expected return: {0} is not convertible to {1}", expectedType, samReturnType)); } foreach (MethodType bridgeMT in AdditionalBridges) { if (!IsAdaptableToAsReturnStrict(expectedType, bridgeMT.ReturnType())) { throw new LambdaConversionException(string.Format("Type mismatch for lambda expected return: {0} is not convertible to {1}", expectedType, bridgeMT.ReturnType())); } } }