2013-02-26 46 views
6

Tôi đang cố gắng xác định xem tôi có cần biên dịch lại một số lọ trong chuỗi xây dựng của chúng tôi hay không, nếu tôi có cấu trúc như sau, jar 1 biên dịch khi thay đổi nguồn và jar 2 biên dịch khi thay đổi nguồn hoặc khi jar 1 đã biên dịch lại.Có thể bytecode của một lớp thay đổi nếu một lớp cha/giao diện thay đổi?

jar 1:

public class Foo /* impl*/ 

jar 2:

public class Bar extends Foo /*impl*/ 

Giả sử hợp đồng giữa 2 lớp không thay đổi, tức là. phương pháp trừu tượng được thêm vào hoặc phương thức được thêm vào giao diện, v.v.

Tôi có cần biên dịch lại jar 2 không? I E. nếu một số thay đổi được thực hiện cho một phương pháp riêng trong Foo Bar sẽ cần phải được biên dịch lại?

Tôi đã thử nghiệm điều này bằng cách so sánh bytecode của hai lớp sau khi thay đổi một bó trong một và như mong đợi nó không thay đổi. Tuy nhiên, đồng nghiệp của tôi nhấn mạnh rằng họ đã gặp phải những tình huống mặc dù hợp đồng không thay đổi nhưng họ phải biên dịch lại mọi thứ để nó hoạt động, tuy nhiên họ không thể nhớ lý do là gì ... điều đó không cần thiết. Có trường hợp nào thực hiện thay đổi đối với siêu lớp hay không sẽ yêu cầu lớp con được biên dịch lại mặc dù giao diện giữa hai vẫn giữ nguyên?

Trả lời

6

Hãy nói rằng Foo được phát hành bởi một tổ chức mã nguồn mở; và có hàng ngàn lớp con của Foo được thực hiện bởi nhiều công ty khác nhau.

Bây giờ, nếu một số thay đổi được thực hiện cho Foo và phiên bản mới được phát hành dưới dạng nhị phân, tất cả các công ty có biên dịch lại mã của họ không? Tất nhiên là không.(tốt, chúng tôi biên dịch lại tất cả các mã mọi lúc, nhưng không bắt buộc - bình mới của Foo có thể đơn giản rơi vào mà không gây ra bất kỳ sự cố nào)

Đây là vấn đề tương thích nhị phân và bạn có thể kiểm tra spec để đảm bảo rằng thay đổi cho Foo là an toàn. xem http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html

+0

Cảm ơn bạn đã liên kết, tôi đoán tôi đã hy vọng rằng miễn là nguồn không thay đổi, tệp lớp sẽ không bao giờ cần phải thay đổi. Oh well. – Andrew

3

Trong trường hợp chung, bạn phải biên dịch lại lớp phụ thuộc. Tuy nhiên nếu bạn không thay đổi bất kỳ phương thức hoặc trường nào của Foo được sử dụng bởi Bar, bạn không phải biên dịch lại Bar khi thay đổi Foo.

Ví dụ nếu Foo có phương pháp protected int foo() gọi bằng Bar nhưng bạn thay đổi nó chữ ký để protected String foo() hay thay đổi mức độ hiển thị private bạn phải tái biên dịch Bar. Trong trường hợp này Bar không thể được biên dịch: bạn phải thay đổi mã của nó.

Tuy nhiên nếu Bar không sử dụng phương pháp foo() hoặc nếu chỉ chi tiết triển khai foo() được thay đổi, bạn có thể sử dụng Bar mà không cần biên dịch lại.

+0

thay đổi giá trị không đổi trong Foo mà Bar sử dụng cũng sẽ yêu cầu biên dịch lại. – jtahlborn

+2

cũng có, java cũng đã xác định các quy tắc cho [khả năng tương thích nhị phân] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html). – jtahlborn

+0

@jtahlborn, cảm ơn bạn đã liên kết đến các quy tắc. Rất hữu dụng. – AlexR

2

Chắc chắn không. Bạn có thể sử dụng các khung công tác (có chứa nhiều lớp học có hợp đồng như Foo) được đóng gói trong tệp jar và bạn không cần phải biên dịch chúng từ nguồn. Nhưng bạn cần phải hoàn toàn chắc chắn rằng hợp đồng đã không được thay đổi trực tiếp trên gián tiếp. Một số exmaple của sự thay đổi gián tiếp:

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; 
    } 
} 

Nếu bạn không biên dịch lại lớp Bar nó vẫn sẽ sử dụng giá trị 1.

+0

Điều đó có nghĩa là tệp Bar.class sẽ có giá trị của 'CONSTANT' int bên trong nó không? Trực giác của tôi sẽ nói rằng nó chỉ có một refrerence để 'Foo/CONSTANT' và sẽ được cập nhật cho phù hợp trong thời gian chạy. Bất kỳ ý tưởng tại sao đó sẽ không phải là trường hợp? – Andrew

+0

nếu bạn sẽ sử dụng cái gì khác hơn _switch_ hơn là có. Lệnh chuyển đổi yêu cầu các số rõ ràng và không thể biên dịch để đọc giá trị từ trường CONSTANT trong thời gian chạy. – ijrandom

Các vấn đề liên quan