public static void main(String[] arg) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); Class thisClass = lookup.lookupClass(); // (who am I?) MethodType methodType; MethodHandle methodHandle; Employee employee = new Employee(); String name; Field fieldName = null; for (Field field : Employee.class.getDeclaredFields()) { if (field.getName().equals("name")) { fieldName = field; fieldName.setAccessible(true); break; } } // Lookup invoke dynamic methodType = MethodType.methodType(String.class); methodHandle = lookup.findVirtual(Employee.class, "getName", methodType); name = (String) methodHandle.invokeExact(new Employee()); System.out.println("invoke dynamic " + name); // Lookup reflection Method method = Employee.class.getMethod("getName", new Class<?>[] {}); name = (String) method.invoke(new Employee()); System.out.println("reflection " + name); // Lookup Handle Field Direct MethodHandle methodHandleFieldDirect = lookup.unreflectGetter(fieldName); name = (String) methodHandleFieldDirect.invokeExact(new Employee()); System.out.println("method handle for field direct " + name); long start = 0; long end = 0; long times = 10_000; long regularTime; long invokeDynamicTime; long reflectionTime; long count = 0; long invokeDynamicTimeUsingField; long fieldDirect; // warm up for (int index = 0; index < times; index++) { employee.getName(); name = (String) methodHandle.invokeExact(employee); name = (String) method.invoke(employee); name = (String) methodHandleFieldDirect.invokeExact(employee); } // regular method call time start = System.nanoTime(); for (int index = 0; index < times; index++) { name = employee.getName(); count += name.hashCode(); } count = 0; end = System.nanoTime(); regularTime = end - start; System.out.printf("regular method call time = %d\n", regularTime / times); // invoke dynamic method call time start = System.nanoTime(); for (int index = 0; index < times; index++) { name = (String) methodHandle.invokeExact(employee); count += name.hashCode(); } count = 0; end = System.nanoTime(); invokeDynamicTime = end - start; System.out.printf("invoke dynamic method call time = %d\n", invokeDynamicTime / times); // reflection method call time start = System.nanoTime(); for (int index = 0; index < times; index++) { name = (String) method.invoke(employee); count += name.hashCode(); } count = 0; end = System.nanoTime(); reflectionTime = end - start; System.out.printf("reflection method call time = %d\n", reflectionTime / times); // start = System.nanoTime(); for (int index = 0; index < times; index++) { name = (String) methodHandleFieldDirect.invokeExact(employee); count += name.hashCode(); } count = 0; end = System.nanoTime(); invokeDynamicTimeUsingField = end - start; System.out.printf( "field method invoke dynamic call time = %d\n", invokeDynamicTimeUsingField / times); // start = System.nanoTime(); for (int index = 0; index < times; index++) { name = (String) fieldName.get(employee); count += name.hashCode(); } count = 0; end = System.nanoTime(); fieldDirect = end - start; System.out.printf("field method reflection call time = %d\n", fieldDirect / times); }
static { Field charsField = AccessController.doPrivileged( new PrivilegedAction<Field>() { @Override public Field run() { Field charsField; try { charsField = String.class.getDeclaredField("value"); charsField.setAccessible(true); } catch (NoSuchFieldException ex) { LOG.info("char array stealing from String not supported", ex); charsField = null; } catch (SecurityException ex) { throw new RuntimeException(ex); } return charsField; } }); MethodHandles.Lookup lookup = MethodHandles.lookup(); if (charsField != null) { try { CHARS_FIELD_GET = lookup.unreflectGetter(charsField); } catch (IllegalAccessException ex) { throw new ExceptionInInitializerError(ex); } } else { CHARS_FIELD_GET = null; } // up until u45 String(int offset, int count, char value[]) { // u45 reverted to: String(char[] value, boolean share) { Constructor<String> prConstr = AccessController.doPrivileged( new PrivilegedAction<Constructor<String>>() { @Override public Constructor<String> run() { Constructor<String> constr; try { constr = String.class.getDeclaredConstructor(char[].class, boolean.class); constr.setAccessible(true); } catch (NoSuchMethodException ex) { try { constr = String.class.getDeclaredConstructor(int.class, int.class, char[].class); constr.setAccessible(true); } catch (NoSuchMethodException ex2) { ex2.addSuppressed(ex); LOG.info("building String from char[] fast not supported", ex2); constr = null; } catch (SecurityException ex2) { ex2.addSuppressed(ex); throw new RuntimeException(ex2); } } catch (SecurityException ex) { throw new RuntimeException(ex); } return constr; } }); if (prConstr == null) { PROTECTED_STR_CONSTR_PARAM_TYPES = null; PROTECTED_STR_CONSTR_HANDLE = null; } else { PROTECTED_STR_CONSTR_PARAM_TYPES = prConstr.getParameterTypes(); try { PROTECTED_STR_CONSTR_HANDLE = lookup.unreflectConstructor(prConstr); } catch (IllegalAccessException ex) { throw new ExceptionInInitializerError(ex); } } }