Java Reflection allows you to inspect interfaces, fields and methods from a known or an unknown class. It also allows you to call methods from these unknown class which otherwise wont be possible.
This post is for inspecting class , methods, constructors, fields from an unknown class. In the next post, I would be sharing on how you could utilize and execute those retrieved methods.
Reference:
http://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful
http://www.javatpoint.com/java-reflection
http://tutorials.jenkov.com/java-reflection/index.html
http://www.oracle.com/technetwork/articles/java/javareflection-1536171.html
Language Used:
Java
Git Location:
https://github.com/csanuragjain/extra/tree/master/ReflectionReadAPI
Related:
https://cooltrickshome.blogspot.in/2017/04/java-reflection-accessingmodifying.html
Pre-requisite:
1) We have a class file named Unknown.class.
2) Unknown.class is the compiled class file and contains the byte code
3) You cannot check the methods and fields from this class unless you deobfuscate the java file
4) You cannot directly call the methods from this class in Eclipse unless and until you copy the java source code which you obtained by deobfuscating this class into a new java file in eclipse. (Or you use Reflection, which we will see :) )
Program:
Obtaining the real class name from Unknown.class:
public static void main(String[] args) {
ClassLoader cl;
Class c;
try {
File file = new File(".");
URL url = file.toURL();
URL[] urls = new URL[]{url};
cl = new URLClassLoader(urls);
c = cl.loadClass("Unknown");
System.out.println(c.isInterface());
} catch (ClassNotFoundException e) {
System.out.println("Requested class was not found "+e.getMessage());
} catch (MalformedURLException e) {
System.out.println("Given class file url was not found "+e.getMessage());
}
}
Output:
How it works:
1) We place the Unknown.class in the current project directory.
2) We make a File object which points to the directory where Unknown.class is present. Since it is present in current directory we keep path as '.'
3) We make a URL object using the above File object and then pass this object in a URL array.
4) We use URLClassLoader to load the class from the URL we created.
5) We retrieve the class instance using loadClass
6) isInterface method tells if Unknown.class is an interface
7) When we run this class we get an error wrong name: com/cooltrickshome/completed/RunExternalProgram
8) This tells that real name of Unknown.class is RunExternalProgram.class and its part of package com.cooltrickshome.completed.RunExternalProgram
9) After knowing this, we create folders com/cooltrickshome/completed inside the current project directory (why: refer step 2)
10) We rename Unknown.class to RunExternalProgram.class and place it inside com/cooltrickshome/completed folder
11) Finally we change loadClass to cl.loadClass("com.cooltrickshome.completed.RunExternalProgram");
12) Folder structure finally becomes ./com/cooltrickshome/completed/RunExternalProgram.class
Obtaining the method name from this class file:
public void printMethods(Class c) {
// Getting all the methods
System.out.println("\nMethods of this class");
Method methlist[] = c.getDeclaredMethods();
for (int i = 0; i < methlist.length; i++) {
Method m = methlist[i];
System.out.println(m.toString());
System.out.println("Method Name: " + m.getName());
System.out.println("Declaring Class: " + m.getDeclaringClass());
Class param[] = m.getParameterTypes();
for (int j = 0; j < param.length; j++)
System.out.println("Param #" + j + ": " + param[j]);
Class exec[] = m.getExceptionTypes();
for (int j = 0; j < exec.length; j++)
System.out.println("Exception thrown by method #" + j + ": "
+ exec[j]);
System.out.println("Method Return type: " + m.getReturnType());
System.out
.println("--------------------------------------------------\n");
}
}
Output:
Methods of this class
public static void com.cooltrickshome.completed.RunExternalProgram.main(java.lang.String[]) throws java.lang.InterruptedException,java.io.IOException
Method Name: main
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: class [Ljava.lang.String;
Exception thrown by method #0: class java.lang.InterruptedException
Exception thrown by method #1: class java.io.IOException
Method Return type: void
--------------------------------------------------
public int com.cooltrickshome.completed.RunExternalProgram.getCounter(int)
Method Name: getCounter
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: int
Method Return type: int
--------------------------------------------------
public void com.cooltrickshome.completed.RunExternalProgram.runProgram(java.lang.String[]) throws java.lang.InterruptedException,java.io.IOException
Method Name: runProgram
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: class [Ljava.lang.String;
Exception thrown by method #0: class java.lang.InterruptedException
Exception thrown by method #1: class java.io.IOException
Method Return type: void
--------------------------------------------------
public void com.cooltrickshome.completed.RunExternalProgram.incrementCounter(int)
Method Name: incrementCounter
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: int
Method Return type: void
--------------------------------------------------
How it works:
1) getDeclaredMethods is used to retrieve the methods from the class passed in argument
2) We iterate through each method in a for loop
3) toString method of this method will print the full function prototype
4) getName is used to print the method name
5) getDeclaringClass is used to print the declaring class
6) getParameterTypes is used to retrieve the parameters type used by this method
7) getExceptionTypes is used to find the exception which this method throws
8) getReturnType is used to retrieve the return type of this method.
Obtaining the Constructors from the class file:
public void printConstructor(Class c) {
// Getting all the constructor
System.out.println("Constructor of this class");
Constructor[] constlist = c.getDeclaredConstructors();
for (int i = 0; i < constlist.length; i++) {
Constructor m = constlist[i];
System.out.println(m.toString());
System.out.println("Method Name: " + m.getName());
System.out.println("Declaring Class: " + m.getDeclaringClass());
Class param[] = m.getParameterTypes();
for (int j = 0; j < param.length; j++)
System.out.println("Param #" + j + ": " + param[j]);
Class exec[] = m.getExceptionTypes();
for (int j = 0; j < exec.length; j++)
System.out.println("Exception thrown by method #" + j + ": "
+ exec[j]);
System.out
.println("--------------------------------------------------\n");
}
}
Output:
Constructor of this class
public com.cooltrickshome.completed.RunExternalProgram()
Method Name: com.cooltrickshome.completed.RunExternalProgram
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
--------------------------------------------------
public com.cooltrickshome.completed.RunExternalProgram(int)
Method Name: com.cooltrickshome.completed.RunExternalProgram
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: int
--------------------------------------------------
How it works:
1) getDeclaredConstructors is used to retrieve the constructors from the class passed in argument
2) We iterate through each constructor in a for loop
3) toString method will print the full constructor prototype
4) getName is used to print the constructor name
5) getDeclaringClass is used to print the declaring class
6) getParameterTypes is used to retrieve the parameters type used by this constructor
7) getExceptionTypes is used to find the exception which this constructor throws
Obtaining the variables from the class file:
public void printFields(Class c)
{ System.out.println("Variables of this class");
Field fieldlist[]
= c.getDeclaredFields();
for (int i
= 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("Variable name: " + fld.getName());
System.out.println("Declaring class: " +fld.getDeclaringClass());
System.out.println("Variable type: " + fld.getType());
int mod = fld.getModifiers();
System.out.println("Modifiers = " +Modifier.toString(mod));
System.out.println("--------------------------------");
}
}
Output:
Variables of this class
Variable name: counter
Declaring class: class com.cooltrickshome.completed.RunExternalProgram
Variable type: int
Modifiers = private
--------------------------------------------------
How it works:
1) getDeclaredFields is used to retrieve the variables from the class passed in argument
2) We iterate through each variable in a for loop
3) getName is used to print the variable name
4) getDeclaringClass is used to print the declaring class
5) getParameterTypes is used to retrieve the variable type used by this variable
7) getModifiers() retrieve the modifier of this variable.
Full Program : (Available from git location)
RunExternalProgram.class:
Placed at <current project directory>/cooltrickshome/completed/RunExternalProgram.class
ReflectionReadApi.java:
package com.cooltrickshome;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
public class ReflectionReadApi {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) {
ClassLoader cl;
Class c;
try {
File file = new File(".");
URL url = file.toURL();
URL[] urls = new URL[] { url };
cl = new URLClassLoader(urls);
c = cl.loadClass("com.cooltrickshome.completed.RunExternalProgram");
System.out.println("\nName of class is " + c.getName());
ReflectionReadApi ra = new ReflectionReadApi();
ra.printMethods(c);
ra.printConstructor(c);
ra.printFields(c);
} catch (ClassNotFoundException e) {
System.out.println("Requested class was not found "
+ e.getMessage());
} catch (MalformedURLException e) {
System.out.println("Given class file url was not found "
+ e.getMessage());
}
}
public void printMethods(Class c) {
// Getting all the methods
System.out.println("\nMethods of this class");
Method methlist[] = c.getDeclaredMethods();
for (int i = 0; i < methlist.length; i++) {
Method m = methlist[i];
System.out.println(m.toString());
System.out.println("Method Name: " + m.getName());
System.out.println("Declaring Class: " + m.getDeclaringClass());
Class param[] = m.getParameterTypes();
for (int j = 0; j < param.length; j++)
System.out.println("Param #" + j + ": " + param[j]);
Class exec[] = m.getExceptionTypes();
for (int j = 0; j < exec.length; j++)
System.out.println("Exception thrown by method #" + j + ": "
+ exec[j]);
System.out.println("Method Return type: " + m.getReturnType());
System.out
.println("--------------------------------------------------\n");
}
}
public void printConstructor(Class c) {
// Getting all the constructor
System.out.println("Constructor of this class");
Constructor[] constlist = c.getDeclaredConstructors();
for (int i = 0; i < constlist.length; i++) {
Constructor m = constlist[i];
System.out.println(m.toString());
System.out.println("Method Name: " + m.getName());
System.out.println("Declaring Class: " + m.getDeclaringClass());
Class param[] = m.getParameterTypes();
for (int j = 0; j < param.length; j++)
System.out.println("Param #" + j + ": " + param[j]);
Class exec[] = m.getExceptionTypes();
for (int j = 0; j < exec.length; j++)
System.out.println("Exception thrown by method #" + j + ": "
+ exec[j]);
System.out
.println("--------------------------------------------------\n");
}
}
public void printFields(Class c)
{
System.out.println("Variables of this class");
Field fieldlist[]
= c.getDeclaredFields();
for (int i
= 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("Variable name: " + fld.getName());
System.out.println("Declaring class: " +fld.getDeclaringClass());
System.out.println("Variable type: " + fld.getType());
int mod = fld.getModifiers();
System.out.println("Modifiers = " +Modifier.toString(mod));
System.out.println("--------------------------------------------------\n");
}
}
}
Output:
Name of class is com.cooltrickshome.completed.RunExternalProgram
Methods of this class
public static void com.cooltrickshome.completed.RunExternalProgram.main(java.lang.String[]) throws java.lang.InterruptedException,java.io.IOException
Method Name: main
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: class [Ljava.lang.String;
Exception thrown by method #0: class java.lang.InterruptedException
Exception thrown by method #1: class java.io.IOException
Method Return type: void
--------------------------------------------------
public void com.cooltrickshome.completed.RunExternalProgram.runProgram(java.lang.String[]) throws java.lang.InterruptedException,java.io.IOException
Method Name: runProgram
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: class [Ljava.lang.String;
Exception thrown by method #0: class java.lang.InterruptedException
Exception thrown by method #1: class java.io.IOException
Method Return type: void
--------------------------------------------------
public int com.cooltrickshome.completed.RunExternalProgram.getCounter(int)
Method Name: getCounter
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: int
Method Return type: int
--------------------------------------------------
public void com.cooltrickshome.completed.RunExternalProgram.incrementCounter(int)
Method Name: incrementCounter
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: int
Method Return type: void
--------------------------------------------------
Constructor of this class
public com.cooltrickshome.completed.RunExternalProgram()
Method Name: com.cooltrickshome.completed.RunExternalProgram
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
--------------------------------------------------
public com.cooltrickshome.completed.RunExternalProgram(int)
Method Name: com.cooltrickshome.completed.RunExternalProgram
Declaring Class: class com.cooltrickshome.completed.RunExternalProgram
Param #0: int
--------------------------------------------------
Variables of this class
Variable name: counter
Declaring class: class com.cooltrickshome.completed.RunExternalProgram
Variable type: int
Modifiers = private
--------------------------------------------------
Hope it helps :)