Lesson 08 - Reflection API, Annotations

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 34

Lesson 8 – Reflection API, Annotations

Lesson goals

▷ JVM and Memory


▷ java.lang.reflect
▷ java.lang.annotation

2
JVM Structure
*.class CLASS LOADER

Runtime Data Area


Heap Memory Non-heap Memory

Java Stack Native method stack


GC

Native Libs
Execution Engine Native Interface *.dll

3
JVM Structure. Java Heap

▷ Java Heap space is used by java runtime to allocate


memory to Objects and JRE classes. Whenever we
create any object, it’s always created in the Heap
space.
▷ Garbage Collection runs on the heap memory to
free the memory used by objects that doesn’t have
any reference. Any object created in the heap space
has global access and can be referenced from
anywhere of the application.

4
JVM Structure. Java Stack
▷ Java Stack memory is used for execution of a thread. They
contain method specific values that are short-lived and references
to other objects in the heap that are getting referred from the
method.
▷ Stack memory is always referenced in LIFO (Last-In-First-Out)
order. Whenever a method is invoked, a new block is created in
the stack memory for the method to hold local primitive values
and reference to other objects in the method.
▷ As soon as method ends, the block becomes unused and become
available for next method.
▷ Stack memory size is very less compared to Heap memory.

5
JVM Structure. Java Heap/Stack

▷ We can use -Xms and -Xmx JVM option to define


the startup size and maximum size of heap memory.
We can use -Xss to define the stack memory size.
▷ When stack memory is full, Java runtime throws
java.lang.StackOverFlowError whereas if heap
memory is full, it throws
java.lang.OutOfMemoryError: Java Heap Space
error.

6
ClassLoader

▷ Class loaders are responsible for loading Java


classes during runtime dynamically to the JVM
▷ It is possible to implement your own Class loader
▷ Almost all Java-based containers such as servlet
containers implement custom ClassLoaders to
support features like hot deployment and runtime
platform extensibility

7
ClassLoader
▷ There are three two types of built-in ClassLoader in Java:
▷ Bootstrap Class Loader – It loads JDK internal classes, typically
loads rt.jar and other core classes for example java.lang.* package
classes
▷ Extensions Class Loader (Platform Class Loader) – It loads classes
from the JDK extensions directory, usually $JAVA_HOME/lib/ext
directory (no longer supported from Java 11)
▷ System Class Loader (Application Class Loader) – It loads classes
from the current classpath that can be set while invoking a
program using –cp or –classpath command line options.

8
ClassLoader

public class ClassLoaderTest {


public static void main(String[] args) {
System.out.println("class loader for HashMap: "
+ java.util.HashMap.class.getClassLoader());
System.out.println("class loader for this class: "
+ ClassLoaderTest.class.getClassLoader());
System.out.println("class loader for external lib class: "
+ com.google.gson.Gson.class.getClassLoader());
}
}

9
ClassLoader
▷ class loader for HashMap:
○ null
▷ class loader for this class:
○ jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd
▷ class loader for external lib class:
○ jdk.internal.loader.ClassLoaders$AppClassLoader@77556fd

10
Native Methods

▷ JNI (Java Native Interface) - standard mechanism for


running code that is written in C/C++ or Assembler
languages, and is assembled as dynamic libraries

Java Application
//native method declaration
public native int nativeMethod();

JNI

DLL

11
Reflection API

▷ The ability to examine or modify the runtime


behavior of applications
○ read properties
○ update data
○ change model

12
Reflection API

13
java.lang.Class

▷ get the metadata of a class at run time


▷ examine and change the run time behavior of a class

14
Class obtaining

▷ forName() method of Class class


○ Class clazz = Class.forName(“edu.chnu.javaforweb.App");

▷ getClass() method of Object class


○ Class clazz = instance.getClass();

▷ the .class syntax


○ Class clazz = App.class

▷ By classloader

15
Class instantiation

try {
Class<App> clazz = App.class;
App app = clazz.newInstance(); //requires no-args constructor
log(app.getName());
} catch (InstantiationException | IllegalAccessException e) {
log("Can not instantiate App by reflection: {}“, e.getMessage());
}

16
Class instantiation

try {
Class[] argTypes = {
int.class, String.class, String.class
};
Constructor<App> constructor = clazz.getConstructor(argTypes);
App app = constructor.newInstance(1, “App", "Some App desc");
log(app); //App{id=1, name=‘App’, description=‘Some App desc’}
} catch (Exception e) {
log("Error: {}", e.getMessage());
}

17
Declared fields

▷ includes public, protected, default (package) access,


and private fields, but excludes inherited fields

Class<App> clazz = App.class;

Field[] declaredFields = clazz.getDeclaredFields();


for (Field field : declaredFields) {
log("\t" + field);
}

18
Fields

▷ includes all the public fields up the entire class


hierarchy

Class<App> clazz = App.class;

Field[] fields = clazz.getFields();


for (Field field : fields) {
log("\t" + field);
}

19
Declared methods

▷ includes public, protected, default (package) access,


and private methods, but excluding inherited
methods

Class<App> clazz = App.class;

Method[] declaredMethods = clazz.getDeclaredMethods();


for (Method method : declaredMethods) {
log("\t" + method);
}

20
Methods

▷ includes all the public methods up the entire class


hierarchy

Class<App> clazz = App.class;

Method[] methods = clazz.getMethods();


for (Method method : methods) {
log("\t" + method);
}

21
Invisible field update
Class<User> userClass = User.class;
User user = new User(1, "John", 20, "UTF");
log(user.name); // John

try {
Field nameField = userClass.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(user, "Roberto");
log(user.name); // Roberto
} catch (NoSuchFieldException | IllegalAccessException e) {
log("Error: {}“, e.getMessage());
}

22
Invisible method invocation

Class<User> userClass = User.class;


User user = new User(1, "John", 20, "UTF");
log(user.name); // John

try {
Method setter = userClass.getDeclaredMethod("setName", String.class);
nameSetter.setAccessible(true);
nameSetter.invoke(user, "Roberto");
log(user.name); // Roberto
} catch (NoSuchMethodException | IllegalAccessException |
InvocationTargetException e) {
log("Error: {}“, e.getMessage());
}
23
Annotations

@Deprecated
@Override
@SuppressWarnings
@FunctionalInterface
@NonNull

24
Annotations. Retention Policy
Retention Policy Description

SOURCE Record component


Annotations are to be recorded in
the class file by the compiler but
CLASS need not be retained by the VM at
run time. This is the default
behavior
Annotations are to be recorded in
the class file by the compiler and
RUNTIME
retained by the VM at run time, so
they may be read reflectively

25
Annotations. Element Type
Element Type Description

Class, interface (including annotation interface),


TYPE
enum, or record declaration

FIELD Field declaration (includes enum constants)

METHOD Method declaration

PARAMETER Formal parameter declaration

CONSTRUCTOR Constructor declaration

LOCAL_VARIABLE Local variable declaration

Annotation interface declaration (Formerly known


ANNOTATION_TYPE
as an annotation type)

PACKAGE Package declaration

TYPE_PARAMETER Type parameter declaration (since 1.8)

TYPE_USE Use of a type (since 1.8)

MODULE Module declaration (since 9)

RECORD_COMPONENT Record component (since 19)


26
Annotations

@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Version {
int min();
int max();

String description() default "";


}

27
Annotations

class ApiClass {
@Version // required attributes are missed
void api0(){}
@Deprecated
@Version(min = 1, max = 2)
void api1(){}
@Version(min = 2, max = 3, description = “Some description")
void api2(){}
}

@Version // wrong target element type


class ApiClass2 {}

28
Class annotations usage

29
Method annotations usage

30
Homework
▷ Implement your own annotations:
○ @Codec(algorithm = Algorithms.MORSE/Algorithms.CAESAR/…) – add this annotation to all
codec classes with algorithm name specified
○ @Key – (can be applied for Vigenere only)
○ @Shift - (can be applied for Caesar only)

31
Homework
▷ Change implementation of DecodersFactory and EncodersFactory:
○ Remove switch statement
○ Find class marked by @Codec annotation with algorithm = {specified algorithm} and
implements Decoder/Encoder interface using Reflection API
○ Create instance of found class by no-arg constructor using Reflection API
○ Set values of key/shift (where appliable) from properties using Reflection API (key/shift
should be marked by appropriate annotation)
○ Throw exception in case annotation used incorrectly:
■ @Codec – used for class that does not implements Decoder/Encoder interface
■ @Key – used for algorithm does not use key (for example: Caesar)
■ @Shift – used for class that does use shift (for example: Morse)

32
Links

▷ Reflection API
▷ Using java reflection
▷ Annotations
▷ Java classloaders

33
Thanks!
Any Questions?

34

You might also like