是否可以将自定义元数据添加到.class文件中?

时间:2012-05-22 21:18:17

标签: java debugging bytecode

我们已经在我们公司使用了liquibase一段时间了,我们已经为数据库迁移设置了持续的集成环境,当补丁发生错误时会破坏工作。

该CI环境的一个有趣的“功能”是破坏有“可能的罪魁祸首”,因为所有补丁都需要有“作者”,错误消息显示作者姓名。

如果你不知道liquibase是什么,那没关系,不是重点。

重点是:错误附加 person 名称对软件开发过程非常有益:问题得到更快解决

所以我在想:Java堆栈跟踪是否可能?

我们是否可能有一个包含人名的堆栈跟踪以及如下所示的行号?

java.lang.NullPointerException
 at org.hibernate.tuple.AbstractEntityTuplizer.createProxy(AbstractEntityTuplizer.java:372:john)
 at org.hibernate.persister.entity.AbstractEntityPersister.createProxy(AbstractEntityPersister.java:3121:mike)
 at org.hibernate.event.def.DefaultLoadEventListener.createProxyIfNecessary(DefaultLoadEventListener.java:232:bob)
 at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:173:bob)
 at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87:bob)
 at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:862:john)

必须从SCM系统中提取这类信息(比如对每个源文件执行“svn blame”)。

现在,忘记将编译时间浪费一分钟:这有可能吗? 要向类文件添加元数据吗?

4 个答案:

答案 0 :(得分:3)

原则上,您可以将自定义信息添加到.class文件(可以添加内容的属性和属性部分)。您必须编写自己的编译器/编译器扩展来执行此操作。无法在源代码中添加某些内容,然后这些内容将显示在类文件中。 您在实践中也会遇到重大问题:

  1. 堆栈跟踪内置/打印的方式不知道您添加到类文件的任何内容。因此,如果你想要像上面所示打印这些东西,你必须破解一些核心的JDK类。
  2. 你想要多少细节?最后一个对给定文件进行任何更改的人?这在实践中并不够精确,除非文件归单个开发人员所有。
  3. 以更精细的粒度添加“last-committed-by”信息,比如说每种方法,甚至更糟糕的是,每行会快速膨胀你的类文件(并且类文件的大小限制为64K)
  4. 作为旁注,是否责备人们查找错误有助于更快地修复错误取决于开发组织的文化。在花费大量时间开发这样的东西之前,请确保你在一个有用的地方工作。

答案 1 :(得分:1)

使用源代码中的annotations向您的类文件添加自定义信息的一种方法。我不知道你如何将这些信息可靠地放在堆栈跟踪中,但你可以创建一个工具来检索它。

答案 2 :(得分:1)

通常,此类功能可以在版本控制系统之上实现。您需要知道版本控制系统中文件的修订版,然后您可以调用blame/annotate命令获取有关谁更改了每个单独行的信息。您不需要将此信息存储到类文件中,只要您可以识别您部署的每个类的修订版(例如,您只部署某些标记或标签)。

如果您在调查堆栈跟踪时不想进入版本控制,则可以将行注释信息存储到类文件中,例如:在构建期间使用类post post,可以在类级别添加自定义注释(使用ASM实现这相对简单)。然后打印堆栈跟踪的记录器可以在运行时读取此注释,类似于showing jar versions

答案 3 :(得分:0)

正如@theglauber正确指出的那样,您可以使用注释添加自定义元数据。 Althougth我不确定你是否无法从实现bean的数据库中检索该信息并装饰自定义异常管理器。