有没有办法让maven和eclipse生成相同的类文件

时间:2016-04-21 14:43:00

标签: java eclipse maven jrebel

我有一个使用maven的java项目。我也使用M2Eclipse插件,所以我可以在项目中使用eclipse。我还使用JRebel,以便类更改自动反映在正在运行的服务器中。

问题是我有时在maven中编译我的项目,有时我会在eclipse中编译它(更确切地说,每当我保存java文件时,eclipse会自动编译类文件)。 eclipse和maven编译器最终会为相同的java源文件生成不同的类文件,因此JRebel通常会不必要地重新加载类。有时数百个类文件会被重新加载,即使它们的代码实际上没有被更改。它只是由一个系统或另一个系统重新编译。

例如,这个空类:

public class Stack {

}

使用maven编译时,产生以下结构:

$ javap -verbose Stack.class 
Classfile /tmp/Stack.class
  Last modified Apr 21, 2016; size 240 bytes
  MD5 checksum faf24015026a9cc09caa2c7388930d9a
  Compiled from "Stack.java"
public class Stack
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#13         // java/lang/Object."<init>":()V
   #2 = Class              #14            // Stack
   #3 = Class              #15            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               LStack;
  #11 = Utf8               SourceFile
  #12 = Utf8               Stack.java
  #13 = NameAndType        #4:#5          // "<init>":()V
  #14 = Utf8               Stack
  #15 = Utf8               java/lang/Object
{
  public Stack();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LStack;
}
SourceFile: "Stack.java"

当用eclipse编译时,产生:

$ javap -verbose Stack.class 
Classfile /tmp/Stack.class
  Last modified Apr 21, 2016; size 240 bytes
  MD5 checksum 0d578ab592aebbb947fa85de391019e5
  Compiled from "Stack.java"
public class Stack
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Class              #2             // Stack
   #2 = Utf8               Stack
   #3 = Class              #4             // java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Methodref          #3.#9          // java/lang/Object."<init>":()V
   #9 = NameAndType        #5:#6          // "<init>":()V
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               LStack;
  #14 = Utf8               SourceFile
  #15 = Utf8               Stack.java
{
  public Stack();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LStack;
}
SourceFile: "Stack.java"

有没有办法可以让这两个系统从同一个源文件编译到同一个类文件,这样JRebel就不会不必要地重新加载类了?

关于可能重复的编辑:

我不相信这是this question的完全重复。那个问题是,使用maven的ecj编译器是否是出于调试原因的正确方法;如何配置它以使用配置文件;甚至可以做到。我的问题是如何让JRebel不重新加载类只是因为当没有代码更改时它们被javac / ecj重新编译。

我的问题的解决方案最终可能类似于另一个问题的答案(例如:配置maven以使用ecj),或者它可能是不同的(例如,配置eclipse以使用javac;或完全不同的东西)。 / p>

2 个答案:

答案 0 :(得分:2)

直接回答这个问题:不,javac和ecj是不同的编译器,因此不会产生相同的输出。当然,他们会阻止错误产生兼容的输出。但是这个问题不是关于兼容性问题,而是关于使用不同的构建触发器和JRebel玩得很好的问题。我不知道JRebel所以我不能建议在这种情况下让它更好玩。

根据@ gregg-449的建议,一种解决方法是将Maven配置为使用ecj,如this answer中所述。

答案 1 :(得分:0)

不仅仅是因为他们与众不同;问题是类文件将被保存,编译,然后在Eclipse中进行编辑时重新加载(毕竟,这是它的重点)。因此,即使类文件的内容没有在语义上进行更改,它仍然会被重新加载。