Here is a custom executor that executes an application by searching for its main in the loaded classes loaded by a custom loader. There is a problem when I try to execute a program using my executor.
The source code of the program being executed can be located on the following link
http://agile.csc.ncsu.edu/SEMaterials/realestate/code/RealEstate.zip
package executorOfLoaderClasses;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import customClassLoader.ClassLoaderOfExtClass;
/**
* @author Sanyam
*
* [email protected]
*/
public class ClassExecutor{
private ClassLoaderOfExtClass classLoader;
private byte[][] ArrayOfClasses;
private String[] ArrayOfBinaryNames;
@SuppressWarnings("rawtypes")
private ArrayList<Class> loadedClasses;
private ArrayList<String> loadedClasesNames;
private Object[] parameters;
@SuppressWarnings("rawtypes")
public ClassExecutor() {
classLoader = new ClassLoaderOfExtClass();
new ArrayList<Class>();
loadedClasses = new ArrayList<Class>();
loadedClasesNames = new ArrayList<String>();
}
@SuppressWarnings("unchecked")
public void execute(File[] file, String[] binaryPaths) {
Object[] actuals = { new String[] { "" } };
Method m = null;
try {
Field classesx=ClassLoaderOfExtClass.class.getDeclaredField("classes");
classesx.setAccessible(true);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
}
/*for (int i = 0; i < file.length; i++) {
for (int j = 0; j < file.length; j++) {
try {
@SuppressWarnings("rawtypes")
Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
//Fied classex=classLoader.getResource("classes");
}catch(Exception e){
}
}
}
Class<?>[]classesxx= getLoadedClasses(classLoader);
System.out.println("Loaded classes have size "+ classesxx.length);*/
for (int i = 0; i < file.length; i++) {
try {
@SuppressWarnings("rawtypes")
Class c = classLoader.loadClassCustom(file[i], binaryPaths[i]);
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
} else {
System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
// System.out.println("Main not found!!!");
// System.out.println("M here");
// e.printStackTrace(); // not printing stack trace
} catch (SecurityException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
System.out.println("No such class definition exist!!");
// TODO Auto-generated catch block
// e.printStackTrace();
}
}
try {
m.invoke(null, actuals);
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@SuppressWarnings({ })
public void execute(ArrayList<byte[]> stuffedFiles,
ArrayList<String> binaryPaths) {
convertToArray(stuffedFiles, binaryPaths);
loadAllClasses(ArrayOfClasses, ArrayOfBinaryNames);
Thread myThread = new MyThread();
myThread.start();
/*Object[] actuals = { new String[] { "" } };
Method m = null;
* Method[] m1= new Method[10]; for (Class c : loadedClasses) {
* m1=c.getMethods(); } for(Method m2: m1){
* System.out.println(m2.getName()); }
System.out.println(loadedClasses.size());
for (Class c : loadedClasses) {
* System.out.println(c.toString());
* System.out.println(c.getConstructors());
// for (int i = 1; i < file.size(); i++) {
* for(Method meth : c.getMethods()){ meth.setAccessible(true);
*
* }
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
break;
} else {
// System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
System.out.println("Program does not contain main");
} catch (SecurityException e) {
e.printStackTrace();
}
}
try {
if(parameters==null){
m.invoke(null, actuals);
}
else{
try {
System.out.println("It Fails Here");
m.invoke(null, parameters);
} catch (Exception e) {
System.out.println("Illegal arguments");
}
}
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
// remove till here
/*TraceParser pr = new TraceParser();
pr.traceCollector();
pr.traceStruct();
ArrayList<SingleTraceStructure> parsedExpressions = pr
.getTracedObjects();
AllStackTraceValidator validator = new AllStackTraceValidator(
parsedExpressions);
finalObjects = validator.getTraceObjects();
for(SingleTraceStructure ob : finalObjects){
validatedTraceObjects.add(ob);
}
TraceObjectsMinimizer tracerObj = new TraceObjectsMinimizer();
tracerObj.sortObjects(finalObjects);*/
/*
* for(SingleTraceStructure obj : finalObjects){
* System.out.println(obj.getCalledBy());
* System.out.println(obj.getClassName()+":"+obj.getMethodName()+":"+
* obj.getCallSequenceNumbr()+obj.getCalledBy()); }
*/
}
private void convertToArray(ArrayList<byte[]> classes,
ArrayList<String> binaryPaths) {
/* = new byte[classes.size()][]; */
ArrayOfClasses = new byte[classes.size()][];
ArrayOfBinaryNames = new String[binaryPaths.size()];
int i = 0;
for (byte[] tempClass : classes) {
ArrayOfClasses[i] = tempClass;
i++;
}
int j = 0;
for (String name : binaryPaths) {
ArrayOfBinaryNames[j] = name;
j++;
}
}
@SuppressWarnings("rawtypes")
public void loadAllClasses(byte[][] classes, String[] names) {
for (int i = 0; i < classes.length; i++) {
System.out.println("Round ----->" + i);
Class c = null;
for (int j = 0; j < classes.length; j++) {
if (classes[j] != null) {
try {
c = classLoader.loadClassCustom(classes[j], names[j]);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("unsucessful");
e.printStackTrace();
}
if (c != null) {
System.out.println("loading successfull");
loadedClasses.add(c);
loadedClasesNames.add(names[j]);
classes[j] = null;
names[j] = null;
} else {
// move on
}
} else {
// do nothing
}
}
}
}
@SuppressWarnings("rawtypes")
public ArrayList<Class> getLoadedClasses() {
return loadedClasses;
}
public void parametersToMain(ArrayList<String> strs){
if(strs!=null){
String[] obj = new String[strs.size()];
int i=0;
for(String str : strs){
obj[i]= (String)str;
i++;
}
parameters=obj;
}
else{
parameters=null;
}
}
// return loaded classes of a loader
public static Class<?>[] getLoadedClasses(final ClassLoader loader){
final Class<?>[] classes = getLoadedClasses(loader);
return classes;
}
public class MyThread extends Thread{
Object[] actuals = { new String[] { "" }};
public void run(){
Method m = null;
/*
* Method[] m1= new Method[10]; for (Class c : loadedClasses) {
* m1=c.getMethods(); } for(Method m2: m1){
* System.out.println(m2.getName()); }
*/
/* System.out.println(loadedClasses.size()); */
for (Class<?> c : loadedClasses) {
/*
* System.out.println(c.toString());
* System.out.println(c.getConstructors());
*/
// for (int i = 1; i < file.size(); i++) {
/*
* for(Method meth : c.getMethods()){ meth.setAccessible(true);
*
* }
*/
try {
if (c.getMethod("main", new Class[] { String[].class }) != null) {
m = c.getMethod("main", new Class[] { String[].class });
break;
} else {
// System.out.println("This class does not contain main");
continue;
}
} catch (NoSuchMethodException e) {
System.out.println("Program does not contain main");
} catch (SecurityException e) {
e.printStackTrace();
}
}
try {
if(parameters==null){
//System.out.println("Invoker of" + actuals[1]);
m.invoke(null, actuals);
}
else{
try {
System.out.println("It Fails Here");
m.invoke(null, parameters);
} catch (Exception e) {
System.out.println("Illegal arguments");
}
}
// CallStack.print();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The problem with my executor is while executing the realestate program genetraes the following error
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at executorOfLoaderClasses.ClassExecutor$MyThread.run(ClassExecutor.java:365)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
at edu.ncsu.realestate.gui.Main.main(Main.java:39)
... 5 more
I realized that while invoking the main I am passing a parameter to the main which is an object of string ""
however realestate program does not take any arguments by default ,so for the time being I changed the argument passed to the method to null just to check whether it works fine now.
and again an error was generated as shown below
java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at executorOfLoaderClasses.ClassExecutor$MyThread.run(ClassExecutor.java:366)
Why is this happening the realestate program as mentioned in the http link does not take any arguments by default.
Is this way of execution buggy to other possible input programs ??
The realestate program I mentioned is working absolutely fine when run in eclipse as a Java application
The Main method you invoke expects either zero or two arguments, but you pass one.
public static void main(String[] args) {
GameMaster master = GameMaster.instance();
MainWindow window = new MainWindow();
GameBoard gameBoard = null;
if(args.length > 0) {
if(args[0].equals("test")) {
master.setTestMode(true);
}
try {
Class c = Class.forName(args[1]); // <-- this is l. 39
gameBoard = (GameBoard)c.newInstance();
}
You should write
Object[] actuals = { new String[] { }};
or
Object[] actuals = { new String[0] };
in order to pass not a single empty argument, but no argument at all.
If main
is the startup method of a Java application, it always has signature
public static void main(String[] args)
For this reason, from the java perspective it will always be a method expecting a single argument, which is an array of strings. So on the command line, you use a variable number of arguments, but within the Java application, it is always a single array. Some developers might declare the arguments as String... args
, which means that you might pass a variable number of strings in the Java application, but that is only syntactic sugar which the compiler will translate into an array creation. For reflection, you will always have to pass the array yourself, as there is no automatic array creation for variadic methods there. So always pass a single argument of type String[]
via reflection.
Method.invoke
takes an Object...
for the arguments, so you can either pass an Object[]
containing all the Java arguments, or you can pass each argument separately and have the compiler construct an Object[]
from those. So it is up to you whether you pass the String[]
array directly to invoke
or wrap it in an Object[]
as you did with your actuals
.