I have a java project that used maven. I also use the M2Eclipse plugin so I can use eclipse with the project. I also use JRebel so that class changes are automatically reflected in a running server.
The problem is that I sometimes compile my project in maven and I sometimes compile it inside eclipse (more accurately, eclipse auto-compiles the class files whenever I save a java file). The eclipse and maven compiler's end up producing different class files for identical java source files, so JRebel is often needlessly reloading classes. Sometimes hundreds of class files get reloaded even though their code hasn't actually changed. It's just been re-compiled by one system or the other.
For example, this empty class:
public class Stack {
}
When compiled with maven, produces the following structure:
$ 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"
And when compiled with eclipse, produces:
$ 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"
Is there a way I can get these two systems to compile to the same class file from the same source file so that JRebel doesn't needlessly reload classes?
Edit Regarding Possible Duplicate:
I don't believe this is an exact duplicate of this question. That question was whether using the ecj compiler from maven was the right way to go for debugging reasons; how to configure it to work with profiles; and can it even be done. My question is just how to get JRebel to not reload classes just because they were re-compiled by javac/ecj when there were no code changes.
The solution to my question could end up being similar to the answer for the other question (eg: configure maven to use ecj), or it could be different (eg configure eclipse to use javac; or something else entirely).