通过反射调用main时为什么会出现这些错误

时间:2012-07-05 07:35:31

标签: java reflection loader

这是一个自定义执行程序,它通过在自定义加载程序加载的已加载类中搜索其主程序来执行应用程序。当我尝试使用执行程序执行程序时出现问题。

正在执行的程序的源代码可以位于以下链接

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
 *         
 *         sanyamgoyal007@gmail.com
 */

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();
            }
        }

    }
}

我的执行程序的问题是在执行房地产程序时会发生以下错误

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

我意识到在调用main时我将一个参数传递给main,这是一个字符串""的对象,但是realestate程序默认不接受任何参数,所以暂时改变了传递的参数到null的方法只是为了检查它现在是否正常工作。

再次产生错误,如下所示

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)

为什么这种情况发生在http链接中提到的房地产计划默认情况下不会采用任何参数。

这种执行方式是否适用于其他可能的输入程序?

我提到的realestate程序在eclipse中作为Java应用程序运行时工作得非常好

1 个答案:

答案 0 :(得分:3)

问题

中代码中的实际错误

您调用的Main方法需要零个或两个参数,但是您传递一个。

    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();
                    }

你应该写

Object[] actuals = { new String[] { }};

Object[] actuals = { new String[0] };

为了不传递一个空参数,但根本没有参数。

有关参数类型的一般信息

如果main是Java应用程序的启动方法,则总是具有签名

public static void main(String[] args)

出于这个原因,从java的角度来看,它总是一个期望单个参数的方法,它是一个字符串数组。所以在命令行上,你使用可变数量的参数,但在Java应用程序中,它始终是一个单独的数组。一些开发人员可能会将参数声明为String... args,这意味着您可能会在Java应用程序中传递可变数量的字符串,但这只是编译器将转换为数组创建的语法糖。对于反射,您将始终必须自己传递数组,因为没有为变量方法创建自动数组。所以总是通过反射传递一个String[]类型的参数。

Method.invoke为参数提供Object...,因此您可以传递包含所有Java参数的Object[],也可以单独传递每个参数并让编译器构造一个{ {1}}来自那些人。因此,您是将Object[]数组直接传递给String[]还是将其包裹在invoke中,就像使用Object[]一样。