我正在试验一种进行静态分析的工具。该工具适用于字节码而不是源代码。 (不过,我也有源代码)。
该工具从字节码输出一些行号,现在我需要一种简单的方法来映射回源代码。 Netbeans/Eclipse 一直这样做(当我单击包含的库中的方法时,IDE 会将我带到源代码(如果它可用)),所以我知道这是可能的。我只是想不出办法。
例如,考虑以下 hello world 程序:
package mypackage;
import java.io.*;
class MyMainClass {
public static void main(String[] args) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String name0 = "Alice";
String name1 = "Bob";
try {
name0 = in.readLine();
}
catch(Exception e) {
System.out.println("Caught an exception!");
}
System.out.println("Hello " + name0 + "!");
System.out.println("Hello " + name1 + "!");
}
}
生成的字节码(从javap获得)是:
Compiled from "MyMainClass.java"
class mypackage.MyMainClass extends java.lang.Object{
mypackage.MyMainClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class java/io/BufferedReader
3: dup
4: new #3; //class java/io/InputStreamReader
7: dup
8: getstatic #4; //Field java/lang/System.in:Ljava/io/InputStream;
11: invokespecial #5; //Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;)V
14: invokespecial #6; //Method java/io/BufferedReader."<init>":(Ljava/io/Reader;)V
17: astore_1
18: ldc #7; //String Alice
20: astore_2
21: ldc #8; //String Bob
23: astore_3
24: aload_1
25: invokevirtual #9; //Method java/io/BufferedReader.readLine:()Ljava/lang/String;
28: astore_2
29: goto 42
32: astore 4
34: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
37: ldc #12; //String Caught an exception!
39: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
42: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
45: new #14; //class java/lang/StringBuilder
48: dup
49: invokespecial #15; //Method java/lang/StringBuilder."<init>":()V
52: ldc #16; //String Hello
54: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
57: aload_2
58: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
61: ldc #18; //String !
63: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
66: invokevirtual #19; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
69: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
72: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
75: new #14; //class java/lang/StringBuilder
78: dup
79: invokespecial #15; //Method java/lang/StringBuilder."<init>":()V
82: ldc #16; //String Hello
84: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
87: aload_3
88: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
91: ldc #18; //String !
93: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
96: invokevirtual #19; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
99: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
102: return
Exception table:
from to target type
24 29 32 Class java/lang/Exception
}
该工具的输出类似于:
<mypackage.MyMainClass> 39, 69, 99
这些对应于字节码行号。手动我可以弄清楚这些行必须对应于源代码中的以下行:
System.out.println("Caught an exception!");
System.out.println("Hello " + name0 + "!");
System.out.println("Hello " + name1 + "!");
但是,我需要自动执行此过程。任何帮助,将不胜感激。
最佳答案
如果您可以访问源文件和相应的行号,任务应该很简单,只需按行加载文件,然后只需选择与该行号对应的行即可。
您的方法的问题在于它依赖于根据 class file format 存储在已编译代码中的可选元数据, 形式为 attributes .有问题的两个,即SourceFile和 LineNumberTable都是可选,这意味着不能保证它们会出现在您的代码中。验证您正在分析的类文件是否已编译为包含此信息!
注意:这些相同的属性用于通过 Throwable.getStackTrace 提供堆栈跟踪信息。 ,如果您想知道的话。
关于java - 如何以自动方式获取给定字节码位置的 Java 源代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10680898/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参