如何在Java程序中对目录下所有类文件执行javap -verbose?
这个问题我之前也碰到过!核心原因是Runtime.exec()并不会像终端shell那样解析通配符*——终端里输入javap -verbose folder/*时,是shell先把*展开成目录下所有.class文件的具体路径,再传给javap;但Java直接把folder/*当作一个完整的文件名传给javap,javap找不到这个文件,自然就没输出了。
给你两种靠谱的解决办法:
方法一:借助Shell解析通配符
直接让bash帮我们处理通配符,把整个命令交给shell执行:
try { // 用bash -c来执行完整命令,让shell解析* Process p = Runtime.getRuntime().exec(new String[]{ "/bin/bash", "-c", "javap -verbose folder/*" }); // 读取javap的标准输出 BufferedReader stdReader = new BufferedReader( new InputStreamReader(p.getInputStream()) ); String line; while ((line = stdReader.readLine()) != null) { System.out.println(line); } stdReader.close(); // 别忘了读取错误输出,避免进程阻塞 BufferedReader errReader = new BufferedReader( new InputStreamReader(p.getErrorStream()) ); while ((line = errReader.readLine()) != null) { System.err.println(line); } errReader.close(); p.waitFor(); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
这种方式简单直接,和你在终端执行的效果完全一致,但缺点是依赖bash,在Windows环境下需要改成cmd.exe /c。
方法二:手动遍历目录构建命令
如果想要跨平台兼容性,或者需要更精细地控制要处理的文件,自己遍历目录下的.class文件再构建命令是更好的选择:
try { File classFolder = new File("folder"); // 过滤出所有.class文件 File[] classFiles = classFolder.listFiles((dir, fileName) -> fileName.toLowerCase().endsWith(".class") ); if (classFiles == null || classFiles.length == 0) { System.out.println("目录下没有找到.class文件"); return; } // 构建javap命令的参数列表 List<String> commandArgs = new ArrayList<>(); commandArgs.add("javap"); commandArgs.add("-verbose"); // 把每个.class文件的绝对路径加入参数 for (File file : classFiles) { commandArgs.add(file.getAbsolutePath()); } Process p = Runtime.getRuntime().exec(commandArgs.toArray(new String[0])); // 读取标准输出和错误输出 BufferedReader stdReader = new BufferedReader( new InputStreamReader(p.getInputStream()) ); String line; while ((line = stdReader.readLine()) != null) { System.out.println(line); } stdReader.close(); BufferedReader errReader = new BufferedReader( new InputStreamReader(p.getErrorStream()) ); while ((line = errReader.readLine()) != null) { System.err.println(line); } errReader.close(); p.waitFor(); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
这种方式不依赖任何shell,不管是Linux、Windows还是Mac都能运行,还能灵活过滤文件(比如只处理特定前缀的类文件)。
最后提醒一下:不管用哪种方法,一定要处理进程的错误输出流——如果只读取标准输出,当javap输出错误信息时,进程可能因为输出缓冲区满而卡住,导致程序无响应。
内容的提问来源于stack exchange,提问作者F_society
相关产品推荐
相关产品推荐

