Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining...

45
Reflection & Dynamic Proxies Java Fundamentals, 2016-11-22 Michael Rasmussen

Transcript of Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining...

Page 1: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection &

Dynamic ProxiesJava Fundamentals, 2016-11-22

Michael Rasmussen

Page 2: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Metaprogramming

• Programming paradigm

– Writing programs that treat programs as data

– The ability to modify, execute, transform,

generate programs, or parts thereof —

including itself — at runtime

– Reflection is often a crucial part thereof

Page 3: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

What is Reflection

Introspection

Modification

Page 4: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection

• What is it good for?

– Examining and/or executing code at

runtime, that was unknown at compile time,

and modify the application’s state.

– Poking around in private state that you

otherwise shouldn’t have access to directly

:)

Page 5: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• Determine class

– hierarchy

– members

– annotations

– attributes

– generics

Page 6: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Modification

• get/set state

• invoke methods

• construct new instances

Page 7: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• Done through methods on Class

• Getter-methods for most

of your heart’s desires!

Page 8: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection• Getting the Class instance:

– Compile time knowledge, use .class:ArrayList.class, String.class, etc

– Find Class from an instance at runtime:

instance.getClass()

– Load a class via ClassLoader:Class.forName("name.of.MyClass", false, classLoader)

classLoader.loadClass("name.of.MyClass")

Page 9: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• Class hierarchical information:

– getSuperclass() : Class

– getInterfaces() : Class[]

Page 10: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• Outer class information

– getEnclosingMethod() : Method

– getEnclosingConstructor() : Constructor

– getEnclosingClass() : Class

– getDeclaringClass() : Class

Page 11: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• Nested class information

– getClasses() : Class[]

– getDeclaredClasses(): Class[]

Page 12: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection• Determine class members:

– For determining members, the introspective getters exist in two versions, declared and non-declared, example:

• getFields

• getDeclaredFields

– Declared version only looks on the specific class and disregardsvisibility, where as the non-declared version looks for public members in the class’ entire hierarchy.

Page 13: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

– Fields:

• getFields() : Field[]getField(name) : Field

– Methods:

• getMethods() : Method[]getMethod(name, params…) : Method

– Constructors:

• getConstructors() : Constructor[]getConstructor(params…) : Constructor

Page 14: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• Annotations:

– getAnnotations() : Annotation[]

– getAnnotation(Class<A>) : A

– isAnnotationPresent(Class<A>) : boolean

– getAnnotationsByType(Class<A>) : A[]

Page 15: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• java.lang.reflect.Member

– getName() : String

– getDeclaringClass() : Class

Method, Field and Constructor all implement Member

Page 16: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection• java.lang.reflect.Member

– getModifiers() : int

• Modifier.isPublic(mod) : booleanModifier.isAbstract(mod) : booleanModifier.isVolatile(mod) : booleanetc…

• Modifiers can overlap between type of members!Only use methods applicable to your member type!

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

Page 17: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Modification

• java.lang.reflect.Field

– set(target, value)

– get(target) : value

– getType(): Class

Page 18: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Modification

• java.lang.reflect.Method

– invoke(target, arguments…) : Object

– getReturnType() : Class

Page 19: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Modification

• java.lang.reflect.Constructor

– newInstance() : Object

– newInstance(arguments…) : Object

Page 20: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection: Introspection

• java.lang.reflect.Executable

– getParameterTypes() : Class[]

– getGenericParameterTypes() : Type[]

– getExceptionTypes() : Class[]

– getGenericExceptionTypes() : Type[]

Page 21: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Reflection• Accessibility

– isAccessible() : boolean

– setAccessible(boolean)

• Follows normal language level accessibility rules for private, protected and package-private members. Use setAccessible to disable accessibility checks (JDK9 changes this).

Page 22: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Method Example

Method addMethod = List.class.getDeclaredMethod("add", Object.class);

List<String> strList = new ArrayList<>();addMethod.invoke(strList, "Hello World");System.out.println(strList.get(0));

addMethod.invoke(strList, 1234);System.out.println(strList.get(1));

Page 23: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Method Example

Method intValue = Integer.class.getDeclaredMethod("intValue");Double d = 12.34;

System.out.println(intValue.invoke(d));

java.lang.IllegalArgumentException:object is not an instance of declaring class

Page 24: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Method Example

for (Method m: obj.getClass().getMethods()) {if (!Modifier.isStatic(m.getModifiers()) &&

Modifier.isPublic(m.getModifiers()) &&m.getParameterCount() == 0 &&m.getReturnType() != void.class &&m.getName().startsWith("get")) {

System.out.println(m.getName() + " => " + m.invoke(obj));}

}

Invoke all public, non-static, zero-arg, non-void

“get”-methods on an object, and write out the return value:

Page 25: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Method Example

for (Method m: Thread.class.getMethods()) {if (m.isAnnotationPresent(Deprecated.class)) {

System.out.println(m);}

}

List all deprecated methods on Thread

Page 26: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Method Example

for (Method m: File.class.getDeclaredMethods()) {for (Class<?> exType: m.getExceptionTypes()) {

if (IOException.class.isAssignableFrom(exType)) {System.out.println(m);break;

}}

}

List all methods on File that declare throwing

IOException or subtype thereof

Page 27: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Field example

Field outField = System.class.getDeclaredField("out");

PrintStream out = (PrintStream) outField.get(null);out.println("Hello World");

Read System.out reflectively, and invoke println

Page 28: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Field exampleField valueField = Integer.class.getDeclaredField("value");valueField.setAccessible(true);

Integer i = 6 * 9;System.out.println(valueField.get(i));

valueField.set(i, 42);System.out.println(valueField.get(i));

System.out.printf("6 * 9 = %d\n", 6 * 9);

Output:54426 * 9 = 42

Page 29: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Constructor example

ArrayList list1 = ArrayList.class.newInstance();

Constructor<ArrayList> con =ArrayList.class.getDeclaredConstructor(int.class);

ArrayList list2 = con.newInstance(10);

Page 30: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Dynamic Proxy

• Implementation of the GoF Proxy design

pattern

• Acts as a surrogate for the real object

Page 31: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Dynamic Proxy

– Allows you to intercept method invocations, modifying or delegating as you see fit

– Allows you to lazily create the delegate, for instance for creating resource heavy objects

– Allows you to update the delegate, pointing to a different instance, transparent to users

Page 32: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Dynamic Proxy

• JDK Dynamic Proxies are created using

java.lang.reflect.Proxy

• They only allow you to proxy interfaces

– There are libraries that allow you to proxy

concrete classes as well

Page 33: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Dynamic Proxy

• Commonly the delegate of the Proxy

implements the interfaces implemented by

the Proxy, but it’s not a requirement!

• A Proxy can be used to implement Duck-

typing in Java!

Page 34: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Dynamic Proxy

ClassLoader classLoader = ...;Class[] interfaces = ...;InvocationHandler invocationHandler = ...;

Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

Page 35: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Dynamic Proxy

public <T> T proxify(Class<T> iface, final Object obj) {ClassLoader classLoader = iface.getClassLoader();Class[] interfaces = new Class[] { iface };

InvocationHandler invocationHandler = new InvocationHandler() {public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {

return m.invoke(obj, args);}

};

return (T)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);}

Page 36: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

– Implement a class containing a

method with the following signature:public <T> T proxify(Class<T> iface, final Object obj)

– The return value of the method should be a

dynamic proxy of the supplied interface, with obj

as the Object it should proxy.

Page 37: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

– The invocation handler of the proxy should do the

following, in this order:

(1) If a method exists on obj that meets all the

requirements for it to implement the invoked

interface method, invoke that method on obj and

return the result.

Unless the method is marked @Deprecated!

Page 38: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

– The invocation handler of the proxy should do the

following, in this order:

(2) If the invoked method adhere to the Design

Patterns for Properties conventions as specified in

the JavaBeanstm specifications (getters/setters),

and such a field exists, then access that field, either

getting or setting its value.

Page 39: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

– The invocation handler of the proxy should do the

following, in this order:

(3) If no match for (1) or (2) was found:

throw a NoSuchMethodException

(from your InvocatioHandler’s invoke method)

Page 40: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

Make tests for

your method!

Page 41: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

Expect the Unexpected!

Page 42: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework: Hints

– How do you compare classes?

– Is a protected method a valid implementation

for a interface method?

– Is void setup(String arg) a setter?

– Can methods be overloaded with different

return types?

– Can interfaces have super interfaces?

Page 43: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Homework

• Homework number: 13

• Due date:

– November 28th

– 21:59:59 UTC (23:59:59 Europe/Tallinn)

• Send to: [email protected]

Page 44: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Flipping true <-> false

Field value = Boolean.class.getDeclaredField("value");value.setAccessible(true);value.set(Boolean.TRUE, new Boolean(false));value.set(Boolean.FALSE, new Boolean(true));

System.out.printf("False == %s\n", false);

if (Boolean.FALSE) {System.out.println("Hello World");

}

Page 45: Java Fundamentals, 2016-11-22 Michael Rasmussen · Reflection •What is it good for? –Examining and/or executing code at runtime, that was unknown at compile time, and modify the

Destroy Integer cacheClass<?> cache = Class.forName("java.lang.Integer$IntegerCache");Field f = cache.getDeclaredField("cache");f.setAccessible(true);Integer[] integers = (Integer[]) f.get(null);Random r = new Random(123456789L);for (int i = 0; i < integers.length; i++) {

int x = r.nextInt(integers.length);Integer tmp = integers[i];integers[i] = integers[x];integers[x] = tmp;

}

int a = 10;int b = 20;System.out.printf("%d + %d = %d \n", a, b, a+b);