1

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

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

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,它是 string 的对象,""但是 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链接中提到的房地产程序默认情况下不接受任何参数。

这种执行方式对其他可能的输入程序有问题吗?

我提到的房地产程序在 Eclipse 中作为 Java 应用程序运行时工作得非常好

4

1 回答 1

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...参数,因此您可以传递Object[]包含所有 Java 参数的 an,也可以单独传递每个参数并让编译器Object[]从这些参数中构造 an。因此,您是否将String[]数组直接传递给invoke或将其包装在一个Object[]中取决于您,就像您对actuals.

于 2012-07-05T07:44:30.210 回答