2013-02-26 12 views
6

Sto cercando di determinare se ho bisogno di ricompilare alcuni jar nella nostra catena di build, se ho per esempio la seguente struttura, jar 1 viene compilato quando il suo 'source cambia e jar 2 viene compilato quando il suo' source cambia o quando jar 1 ha ricompilatoIl bytecode di una classe può cambiare se una classe/interfaccia genitore cambia?

vasetto 1:

public class Foo /* impl*/ 

vaso 2:

public class Bar extends Foo /*impl*/ 

Supponendo che il contratto tra le 2 classi non cambia, cioè. viene aggiunto un metodo astratto o un metodo viene aggiunto a un'interfaccia, ecc.

Devo ricompilare il vaso 2? vale a dire. se alcune modifiche vengono apportate a un metodo privato all'interno di Foo, la barra deve essere ricompilata?

Ho provato a testare questo confrontando il bytecode di due classi dopo aver cambiato un gruppo in uno e come previsto non è cambiato. I miei colleghi, tuttavia, insistono sul fatto che hanno incontrato situazioni in cui, nonostante il contratto fosse immutato, hanno dovuto ricompilare tutto per farlo funzionare, ma non riescono a ricordare quale fosse la ragione ... Quindi l'onere della prova è su di me per dimostrare che questo non dovrebbe essere necessario. C'è un caso in cui apportare una modifica a una superclasse richiede la ricompilazione della sottoclasse anche se l'interfaccia tra i due è rimasta la stessa?

risposta

6

Diciamo Foo viene rilasciato da un'organizzazione open source; e ci sono migliaia di sottoclassi di Foo implementate da varie società.

Ora se vengono apportate alcune modifiche a Foo e una nuova versione è rilasciata in formato binario, tutte le società dovrebbero ricompilare il proprio codice? Ovviamente no.(beh, è ​​necessario ricompilare tutto il codice tutto il tempo, ma non è necessario - il nuovo jar di può essere semplicemente inserito senza causare problemi)

Questo è il problema della compatibilità binaria, e puoi controllare il spec per assicurarsi che una modifica a Foo sia sicura. vedi http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html

+0

Grazie per il link, credo che speravo che finché la sorgente non fosse cambiata, il file di classe non avrebbe mai dovuto cambiare. Oh bene. – Andrew

3

In genere è necessario ricompilare la classe dipendente. Tuttavia, se non sono stati modificati metodi o campi di Foo utilizzati da Bar, non è necessario ricompilare Bar quando viene modificato Foo.

Per esempio, se Foo avevano metodo protected int foo() chiamato da Bar ma è cambiato firma protected String foo() o cambiato la sua visibilità a private si deve ri-compilazione Bar. In questo caso non è possibile compilare Bar: è necessario modificarne il codice.

Tuttavia, se Bar non utilizzare il metodo foo() o se solo i dettagli di implementazione di foo() sono stati cambiati è possibile utilizzare Bar senza ri-compilazione.

+0

cambiando un valore costante in Foo quale barra richiede anche una ricompilazione. – jtahlborn

+2

Inoltre, java ha regole ben definite per [compatibilità binaria] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html). – jtahlborn

+0

@jtahlborn, grazie per il link alle regole. Molto utile. – AlexR

2

Definitivamente No. È possibile utilizzare framework (che contengono un sacco di classi con contratto come Foo) che sono inclusi nel file jar e non è necessario compilarli dal sorgente. Ma devi essere assolutamente sicuro che il contratto non sia stato modificato direttamente indirettamente. Alcuni exmaple del cambiamento indiretto:

public class Foo { //v1 
    public static final int CONSTANT = 1;   
} 

public class Foo { //v2 
    public static final int CONSTANT = 2;   
} 

public class Bar extends Foo { 
    private int a(int value) { 
     switch (value) { 
      case CONSTANT: 
       return 1; 
     } 
     return 2; 
    } 
} 

Se non ricompilare classe Bar sarà ancora utilizzare il valore 1.

+0

Significa che il file Bar.class avrà il valore di 'CONSTANT' int al suo interno? La mia intuizione direbbe che ha solo un rifrimento a 'Foo/CONSTANT' e sarà aggiornata di conseguenza in fase di runtime. Qualche idea sul perché non sarebbe il caso? – Andrew

+0

se userete qualcosa di diverso da _switch_ piuttosto che probabilmente sì. L'istruzione switch richiede numeri espliciti e non è possibile per la compilazione leggere il valore dal campo CONSTANT in runtime. – ijrandom

Problemi correlati