From shell, is there a Java tool to check which compiled .class file(s) have a main method?

huangapple go评论72阅读模式
英文:

From shell, is there a Java tool to check which compiled .class file(s) have a main method?

问题

我正在编写一些(Python)脚本,以帮助我自动化批量评分数百个简单的学生 Java 代码库。它们并不都具有相同的目录结构或文件命名。我已经遍历了它们并进行了编译,如果我做假设,我可以运行它们并测试它们等等。但我想知道是否有一种方法可以找到包含了 main() 方法的“主要” .class 文件,这样我就不必对它们的文件命名做出假设(这种假设也并不总是有效)。

我知道 Java 的反射机制,所以我知道我可以编写另一个简单的帮助程序来帮助我识别它。但我想知道是否已经存在任何东西(java 命令行选项,JDK 中的工具等)来测试一个 .class 文件,以查看它是否具有 main() 方法。

英文:

I'm putting together some (Python) scripts to help me automate some of my grading of hundreds of simple student Java repos. Not all of them have the same directory structure or naming of files. I've traversed them all and compiled them and if I make assumptions I can run them and test them, etc. But I'd like to know if there's a way I could find the "main" .class that has the main() method in it, so that I don't have to make assumptions about their file naming (which wouldn't work all the time anyway).

I'm aware of reflection, so yes, I know I could write another simple helper Java program to assist me in identifying it myself. But I was wondering if anything already exists (java command line option, tool from the jdk, etc.) to test a .class file to see if it is has the main() method in it.

答案1

得分: 1

我在想是否已经存在任何东西(java命令行选项,JDK中的工具等)来测试一个 .class 文件,以查看它是否有 main() 方法。

在Java SE中没有直接执行这项任务的工具或选项。

我知道我可以编写另一个简单的Java程序来帮助我...

编写一个 shell 脚本会更简单,它可以遍历文件树,找到 .class 文件,在其上调用 javap,然后使用 grep 来查找具有适当的 main 方法签名的方法。

或者您可以在源代码树上进行类似的操作。


(回想起来,您应该设置任务要求,让学生必须为包含他们的 main 方法的类使用指定的类和包名称。但现在已经太迟了...)

英文:

> I was wondering if anything already exists (java command line option, tool from the JDK, etc.) to test a .class file to see if it is has the main() method in it.

There is no tool or option in Java SE that does that directly.

> I know I could write another simple helper Java program to assist me ...

It would be simpler to write a shell script that iterates a file tree, finds .class files, calls javap on them, and greps for a method with the appropriate main method signature.

Or you could do something similar on the source code tree.


(In retrospect, you should have set the assignment requirements so that the students had to use a specified class and package name for the class containing their main method. But it is too late for that now ...)

答案2

得分: 1

在 C++ 时代,分发头文件以使用共享对象文件是一件大事。人们会只拿到其中一个,而没有同时拿到两者,而且总有可能会出现不匹配的版本。

Java 通过 javap 来解决了这个问题,它可以打印已编译的 .class 文件的方法(以及其他主要接口)。

要测试一个类文件是否有一个主函数,运行以下命令:

javap SomeFile.class

这将列出所有的公共接口。在该列表中,查看是否有 "main entry point":

public static void main(java.lang.String[])

现在,为了大规模处理这个问题,只需创建一个 Python 脚本,其中包括以下步骤:

  1. 定位所有相关的类。
  2. 在类上运行 javap
  3. 读取输出以查找与 "public static void main(java.lang.String[])" 匹配的方法(在开头,因为末尾可能有可变数量的异常)。

这样,你就能找到所有的入口点。

请记住,有时单个库或 JAR 文件可能有多个入口点,其中一些并不是主要入口点。

英文:

In the C++ days, distributing the headers files to use a shared object file was a big deal. People would get one or the other without both, and there was always the chance you'd get mis-matched versions.

Java fixed that with javap which prints the methods (and other major interfaces) of a compiled .class file.

To test if a class file has a main, run

javap SomeFile.class

which will list all public interfaces. Within that list, see if it has the "main entry point"

public static void main(java.lang.String[])

Now to handle this in mass, simply create a Python script that:

  1. Locates all the relevant classes.
  2. Runs javap on the class.
  3. Reads the output for a method that matches (at the beginning, as there can be a variable number of Exceptions at the end "public static void main(java.lang.String[])

And you'll find all entry points.

Keep in mind that sometimes a single library or JAR file has many entry points, some of which are not intended as the primary entry point.

答案3

得分: 0

好的,以下是翻译好的内容:

简单地调用 java -cp . <file> 将在以下情况下完全崩溃:如果类没有 main 方法,或者将运行相关的代码。现在,如果代码在运行时失败并出现错误,您可能会将其视为与没有 main 方法相同的效果。

public class HasMain {
    public static void main(String[] args) {
        System.out.println("Hit main");
    }
}

public class HasDoIt {
    public static void doIt(String[] args) {
        System.out.println("Hit doIt");
    }
}

public class WillBlowUp {
    public static void main(String[] args) {
        System.out.println("Hit blowUp");
        throw new IllegalStateException("oops");
    }
}

使用 PowerShell:

PS D:\Development\sandbox> javac HasMain.java
PS D:\Development\sandbox> javac HasDoIt.java
PS D:\Development\sandbox> javac WillBlowUp.java

PS D:\Development\sandbox> java -cp . HasMain
Hit main

PS D:\Development\sandbox> $?
True

PS D:\Development\sandbox> java -cp . HasDoIt
Error: 在类 HasDoIt 中找不到 main 方法请定义 main 方法例如
   public static void main(String[] args)
或者 JavaFX 应用程序类必须扩展 javafx.application.Application

PS D:\Development\sandbox> $?
False

PS D:\Development\sandbox> java -cp . WillBlowUp
Hit blowUp
Exception in thread "main" java.lang.IllegalStateException: oops
    at WillBlowUp.main(WillBlowUp.java:4)

PS D:\Development\sandbox> $?
False

因此简单地检查返回值可能是一种快速测试类是否具有所需内容的方法尽管任何类似于 exit(1) 的返回都将抛出 false-false

<details>
<summary>英文:</summary>

Well simply calling `java -cp . &lt;file&gt;` will either completely blow out if the class doesn&#39;t have a `main` method or will run the relevant code. Now, if the code fails to run right and errors out you may see it as the same effect as not having a `main` method.

    public class HasMain {
    	public static void main(String[] args) {
    		System.out.println(&quot;Hit main&quot;);
    	}
    }
    public class HasDoIt {
    	public static void doIt(String[] args) {
    		System.out.println(&quot;Hit doIt&quot;);
    	}
    }
    public class WillBlowUp {
    	public static void main(String[] args) {
    		System.out.println(&quot;Hit blowUp&quot;);
    		throw new IllegalStateException(&quot;oops&quot;);
    	}
    }

Using PowerShell:

    PS D:\Development\sandbox&gt; javac HasMain.java
    PS D:\Development\sandbox&gt; javac HasDoIt.java
    PS D:\Development\sandbox&gt; javac WillBlowUp.java

    PS D:\Development\sandbox&gt; java -cp . HasMain                                                                                                                                                                                                                                  
    Hit main

    PS D:\Development\sandbox&gt; $?                                                                                                                                                                                                                                                  
    True

    PS D:\Development\sandbox&gt; java -cp . HasDoIt                                                                                                                                                                                                                                  
    Error: Main method not found in class HasDoIt, please define the main method as:
       public static void main(String[] args)
    or a JavaFX application class must extend javafx.application.Application

    PS D:\Development\sandbox&gt; $?                                                                                                                                                                                                                                                  
    False

    PS D:\Development\sandbox&gt; java -cp . WillBlowUp                                                                                                                                                                                                                               
    Hit blowUp
    Exception in thread &quot;main&quot; java.lang.IllegalStateException: oops
        at WillBlowUp.main(WillBlowUp.java:4)

    PS D:\Development\sandbox&gt; $?                                                                                                                                                                                                                                                  
    False

So simply checking return values could be a quick way to test if the class has what you want, albeit any exit(1) type return will throw a false-false

</details>



huangapple
  • 本文由 发表于 2020年8月30日 10:00:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63653301.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定