private static MethodHandle findConstructor(String className, MethodType methodType) { try { return MethodHandles.publicLookup().findConstructor(Class.forName(className), methodType); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } }
private static Optional<MethodHandle> unreflect(Method method) { try { return Optional.of(MethodHandles.publicLookup().unreflect(method)); } catch (IllegalAccessException ex) { LOGGER.log(Level.FINER, ex, () -> "Access checking fails on " + method.getDeclaringClass() + " class, method '" + method.getName() + "' with parameters " + Arrays.asList(method.getParameters()) + "."); } return Optional.empty(); }
static Optional<MethodHandle> findConstructor(Class<?> type, Class<?>... parameterTypes) { try { Constructor<?> constructor = type.getConstructor(parameterTypes); if (checkConstructor(constructor, parameterTypes.length > 0)) { return Optional.of(MethodHandles.publicLookup().unreflectConstructor(constructor)); } else { LOGGER.log(Level.FINEST, () -> "Class " + type.getName() + " constructor with parameters " + Arrays.toString(parameterTypes) + " cannot be used."); } } catch (NoSuchMethodException ex) { LOGGER.log(Level.FINEST, ex, () -> "Class " + type.getName() + " does not have a constructor with parameters " + Arrays.toString(parameterTypes) + "."); } catch (IllegalAccessException ex) { LOGGER.log(Level.FINER, ex, () -> "Access checking fails on " + type.getName() + " class, constructor with parameters " + Arrays.toString(parameterTypes) + "."); } return Optional.empty(); }
@SuppressWarnings("unchecked") static <T> PropertyAccessor<T> createPropertyAccessor(Class<T> type, String name, Method method) { try { final Class<T> propertyType = (Class<T>) method.getParameterTypes()[0]; Class<?> configAsType = propertyType; boolean list = configAsType.isAssignableFrom(List.class); if (list) { Type genType = method.getGenericParameterTypes()[0]; if (genType instanceof ParameterizedType) { configAsType = (Class<?>) ((ParameterizedType) genType).getActualTypeArguments()[0]; } else { throw new ConfigException("Unable to find generic type of List on setter parameter: " + method); } } MethodHandle handle = MethodHandles.publicLookup() .findVirtual(type, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes())); return new PropertyAccessor<>(name, propertyType, configAsType, list, handle, method.getAnnotation(Value.class)); } catch (NoSuchMethodException | IllegalAccessException | ClassCastException ex) { throw new ConfigException("Cannot access setter: " + method, ex); } }
try { Class<?> kclUserRecordclass = Class.forName("com.amazonaws.services.kinesis.clientlibrary.types.UserRecord"); MethodHandles.Lookup lookup = MethodHandles.publicLookup();
@SuppressWarnings("unchecked") static <T> PropertyAccessor<T> createPropertyAccessor(Class<T> type, String name, Field field) { try { final Class<T> propertyType = (Class<T>) field.getType(); Class<?> configAsType = propertyType; boolean list = configAsType.isAssignableFrom(List.class); if (list) { Type genType = field.getGenericType(); if (genType instanceof ParameterizedType) { configAsType = (Class<?>) ((ParameterizedType) genType).getActualTypeArguments()[0]; } else { throw new ConfigException("Unable to find generic type of List on field type: " + field); } } MethodHandle handle = MethodHandles.publicLookup() .findSetter(type, field.getName(), field.getType()); return new PropertyAccessor<>(name, propertyType, configAsType, list, handle, field.getAnnotation(Value.class)); } catch (NoSuchFieldException | IllegalAccessException | ClassCastException ex) { throw new ConfigException("Cannot access field: " + field, ex); } }
private MethodHandle defineClass() { MethodType mt = MethodType.methodType(Class.class, String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class); MethodHandle m; try { m = MethodHandles.publicLookup().findVirtual(Unsafe.class, "defineClass", mt); } catch(NoSuchMethodException | IllegalAccessException e) { throw new ObjenesisException(e); } Unsafe unsafe = UnsafeUtils.getUnsafe(); return m.bindTo(unsafe); }
private <T> Optional<Function<T, Supplier<PollingStrategy>>> custom(Class<?> clazz, Config properties, Class<T> targetType) { Function<T, Supplier<PollingStrategy>> pollingStrategyFunction; if (PollingStrategy.class.isAssignableFrom(clazz)) { // set class is PollingStrategy implementation try { // use public constructor with target parameter Constructor<?> constructor = clazz.getConstructor(targetType); MethodHandle constructorHandle = MethodHandles.publicLookup().unreflectConstructor(constructor); pollingStrategyFunction = customSupplier(constructorHandle); } catch (NoSuchMethodException | IllegalAccessException ex) { LOGGER.log(Level.FINE, ex, () -> clazz.getName() + " does not have public constructor with single parameter (" + targetType.getName() + "). Generic instance from Config will be used."); // use generic mapping as a fallback pollingStrategyFunction = target -> (Supplier<PollingStrategy>) properties.as(clazz).get(); } } else { // use builder pattern as a fallback throw new ConfigException("Configured polling strategy class " + clazz.getName() + " does not implement PollingStrategy"); } return Optional.ofNullable(pollingStrategyFunction); }
@Test public void testStaticFieldRemoved() throws Throwable { MethodHandle getter = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class); MethodHandle setter = MethodHandles.publicLookup().findStaticSetter(A.class, "fieldA", int.class); A.fieldA = 3; A.fieldB = 5; assertEquals(3, getter.invoke()); // Remove fieldA __toVersion__(2); try { getter.invoke(); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } try { setter.invoke(15); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } }
@Test public void testStaticFieldTypeChange() throws Throwable { MethodHandle getter = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class); MethodHandle setter = MethodHandles.publicLookup().findStaticSetter(A.class, "fieldA", int.class); A.fieldA = 3; A.fieldB = 5; assertEquals(3, getter.invoke()); // Remove fieldA __toVersion__(3); try { getter.invoke(); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } try { setter.invoke(15); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } } }
@Test public void testStaticFieldChangeOrder() throws Throwable { MethodHandle getter = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class); MethodHandle setter = MethodHandles.publicLookup().findStaticSetter(A.class, "fieldA", int.class); A.fieldA = 3; A.fieldB = 5; assertEquals(3, getter.invoke()); // Swap fields A and B __toVersion__(1); assertEquals(3, getter.invoke()); setter.invoke(12); assertEquals(12, A.getFieldA()); assertEquals(12, getter.invoke()); }
@Test public void testFieldRemoved() throws Throwable { A a = new A(); MethodHandle getter = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class); MethodHandle setter = MethodHandles.publicLookup().findSetter(A.class, "fieldA", int.class); a.fieldA = 3; assertEquals(3, getter.invoke(a)); // Remove fieldA __toVersion__(2); try { getter.invoke(a); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } try { setter.invoke(a, 10); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } }
@Test public void testFieldTypeChange() throws Throwable { A a = new A(); MethodHandle getter = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class); MethodHandle setter = MethodHandles.publicLookup().findSetter(A.class, "fieldA", int.class); a.fieldA = 3; assertEquals(3, getter.invoke(a)); // Remove fieldA __toVersion__(3); try { getter.invoke(a); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } try { setter.invoke(a, 10); Assert.fail("Handle should have been cleared!"); } catch (NullPointerException e) { // Handle was cleared! } } }
@Test public void testFieldChangeOrder() throws Throwable { A a = new A(); MethodHandle getter = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class); MethodHandle setter = MethodHandles.publicLookup().findSetter(A.class, "fieldA", int.class); a.fieldA = 3; assertEquals(3, getter.invoke(a)); // Swap fields __toVersion__(1); assertEquals(3, getter.invoke(a)); setter.invoke(a, 53); assertEquals(53, a.getFieldA()); assertEquals(53, getter.invoke(a)); }
@Test public void testStaticInterfaceMethods() throws Throwable { assert __version__() == 0; MethodHandle handle = MethodHandles.publicLookup().findStatic(A.class, "staticMethod", MethodType.methodType(int.class)); assertEquals(1, A.staticMethod()); assertEquals(1, handle.invoke()); __toVersion__(1); assertEquals(2, A.staticMethod()); assertEquals(2, handle.invoke()); __toVersion__(0); } }
private static TemporalAccessor getParse(Class<? extends TemporalAccessor> date, DateTimeFormatter format, String value) throws Throwable { MethodHandle methodHandle = parseDateMap.computeIfAbsent(date, method -> { MethodHandles.Lookup lookup = MethodHandles.publicLookup(); try { return lookup.findStatic(date, METHOD_NAME, MethodType.methodType(date, CharSequence.class, DateTimeFormatter.class)); } catch (Exception e) { throw new RuntimeException(e); } }); return (TemporalAccessor) methodHandle.invokeWithArguments(value, format); }
private static TemporalAccessor getParse(Class<? extends TemporalAccessor> date, String value) throws Throwable { MethodHandle methodHandleSimple = simpleParseDateMap.computeIfAbsent(date, method -> { MethodHandles.Lookup lookup = MethodHandles.publicLookup(); try { return lookup.findStatic(date, METHOD_NAME, MethodType.methodType(date, CharSequence.class)); } catch (Exception e) { throw new RuntimeException(e); } }); return (TemporalAccessor) methodHandleSimple.invokeWithArguments(value); }
DtoMetaProperty(TypeManager typeManager, PropertyDescriptor descriptor, Class<?> dtoType) throws IllegalAccessException, NoSuchMethodException { this.dtoType = dtoType; this.name = descriptor.getName(); Method writeMethod = descriptor.getWriteMethod(); if (writeMethod != null) { Class<?> propertyType = descriptor.getPropertyType(); MethodHandles.Lookup lookup = MethodHandles.publicLookup(); this.setter = lookup.findVirtual(dtoType, writeMethod.getName(), MethodType.methodType(void.class, propertyType)); this.scalarType = typeManager.getScalarType(propertyType); } else { this.scalarType = null; this.setter = null; } }
DtoMetaConstructor(TypeManager typeManager, Constructor<?> constructor, Class<?> someClass) throws NoSuchMethodException, IllegalAccessException { this.types = constructor.getParameterTypes(); this.scalarTypes = new ScalarType[types.length]; for (int i = 0; i < types.length; i++) { scalarTypes[i] = typeManager.getScalarType(types[i]); } MethodHandles.Lookup lookup = MethodHandles.publicLookup(); this.handle = lookup.findConstructor(someClass, typeFor(types)); }
@Override public void bind(Context ctx) throws IllegalAccessException { log.debug("bind %s to context", method); MethodHandle boundHandle = MethodHandles.publicLookup().unreflect(method).bindTo(ctx.getProcessor(processorClass)); if (hasContextParameter()) { boundHandle = boundHandle.bindTo(ctx); } this.methodHandle = boundHandle.asSpreader(Object[].class, arity); }