2010-01-11 4 views
13

Trong dự án Java của tôi, tôi đang sử dụng hai khung công tác khác nhau (giả sử A.jar và B.jar) và cả hai đều yêu cầu một khung công tác chung (ví dụ như Log4j.jar) nhưng trong hai phiên bản khác nhau. Làm thế nào nó được xử lý bởi Java nếu khung A cần Log4J v1.1 và B cần Log4j v1.2? Nó sẽ gây ra một số loại xung đột/lỗi hoặc sẽ bằng cách nào đó (như thế nào?) Giải quyết?Điều gì sẽ xảy ra khi hai khung công tác Java cần thứ ba nhưng mỗi một trong hai cần phiên bản thứ ba khác nhau?

Nếu nó không gây xung đột/lỗi (dự án của tôi có thể được biên soạn và chạy) - tôi có thể sử dụng bất kỳ phiên bản nào của Log4j trong dự án này không? Hoặc tôi buộc phải chọn số phiên bản thấp hơn/cao hơn của Log4j?

Cập nhật:cụ thể hơn ... gì nếu một số phần của Log4j API thay đổi trong v1.2 (giả sử một phương pháp duy nhất DoIT() chữ ký thay đổi) và cả A và B gọi DoIT. Chuyện gì sẽ xảy ra? Dự án của tôi có chạy không? Nó sẽ sụp đổ về việc sử dụng đầu tiên của doIt? Phiên bản nào của Log4j tôi phải đặt trên classpath - v1.2 hoặc cả hai?

+0

Không có câu trả lời chung cho điều này, bạn cần phải cụ thể hơn – skaffman

+0

@skaffman - ok, tôi đã thêm một số thông tin và câu hỏi bổ sung. .. – WildWezyr

Trả lời

3

Java không natively hỗ trợ việc quản lý nhiều phiên bản của cùng một đoạn mã , nghĩa là, bạn chỉ có thể sử dụng tối đa một phiên bản trong cùng một JVM (với trình nạp lớp mặc định).Tuy nhiên, thanh toán câu hỏi 1705720, trong đó có một số câu trả lời chỉ ra những cách có thể đạt được điều đó (OSGi hoặc trình nạp lớp tùy chỉnh).

Nhưng tôi nghi ngờ nó đáng giá khi gặp phải sự cố do nhiều phiên bản log4j không yêu cầu bởi mã của bạn. Trong trường hợp của bạn, tôi khuyên bạn nên bắt đầu sử dụng phiên bản log4j mới hơn (v1.2) trước và xác minh xem nó có gây ra bất kỳ vấn đề nào cho framework A. Nếu nó gây xung đột, sau đó quay trở lại log4j v1.1 và xác minh lại. Nếu bạn thực sự không may mắn, thì bạn cần phải làm cho đôi tay của bạn bị bẩn ...

Cập nhật: cho bạn mô tả cụ thể, không có cách nào để sử dụng log4j v1.1 hoặc v1.2, như khung A và B mỗi yêu cầu chữ ký khác nhau. Bạn phải cuộn phiên bản của riêng bạn của bất kỳ log4j hoặc khung A, hoặc B.

+0

Điều đó có nghĩa là "không có cách nào" - chính xác điều gì sẽ xảy ra nếu tôi cố gắng? Nó sẽ không biên dịch? Nó sẽ sụp đổ khi chạy - khi tải hoặc sau này (ngày đầu tiên sử dụng phương pháp trung gian doIt)? – WildWezyr

+2

giả sử bạn đặt log4j-1.1.jar, log4j-1.2.jar vào đường dẫn lớp của bạn trong chuỗi đó, lớp (phiên bản) từ log4j-1.1.jar sẽ được sử dụng. việc tìm kiếm lớp sẽ dừng lại miễn là nó tìm thấy một. vì vậy kể từ v1.1 được sử dụng, bất kỳ mã nào mong đợi chữ ký của log4j v1.2 sẽ có vấn đề (phương pháp không tìm thấy). – bryantsai

11

Trong sơ đồ tải lớp phẳng, không có hỗ trợ phiên bản thư viện. Bạn cần sử dụng phiên bản mới nhất của thư viện và xóa các phiên bản khác khỏi đường dẫn lớp.

Một số khung công tác, như OSGi, cung cấp các cơ chế để xử lý các trường hợp này, nhưng không rõ ràng bạn đang dựa vào khung trình cắm thêm hay chưa.


Edit:

gì nếu một số phần của Log4j API thay đổi trong v1.2 (giả sử một phương pháp duy nhất doIt() chữ ký thay đổi) và cả A và B gọi doIt. Chuyện gì sẽ xảy ra? Dự án của tôi có chạy không? Nó sẽ sụp đổ khi sử dụng lần đầu tiên của doIt?

Cuộc gọi dựa vào chữ ký không có mặt sẽ có khả năng dẫn đến NoSuchMethodError. Điều này có thể sẽ không xảy ra cho đến khi phương thức được gọi. Các lỗi khác có thể xảy ra nếu các cơ chế khác dựa vào chữ ký (ví dụ: kế thừa lớp).

Phiên bản Log4j nào tôi phải đặt trên classpath - v1.2 hoặc cả hai?

Làm hai phiên bản của thư viện trên đường dẫn lớp sẽ chỉ dẫn đến một tập hợp các lớp được tải ngẫu nhiên. Hành vi sẽ không xác định, nhưng có khả năng có thể dẫn đến tất cả các loại lỗi và ngoại lệ khó chịu.

3

Nếu may mắn chọn một phiên bản của bình bên thứ ba sẽ chỉ hoạt động. Cuối cùng, người ta cần một container để hiểu và cho phép phiên bản của các thành phần cùng tồn tại, giống như OSGI.

0

Mặc dù không được đề xuất nhưng bạn có thể sử dụng cả hai phiên bản. Đặt mỗi phiên bản ở một nơi mà chỉ có khung đó mới có thể xem.

Giải pháp tối ưu sẽ được để có được phiên bản cuối cùng của cả A và B, nơi mà cả hai sử dụng các thư viện chung cuối cùng

+0

Bạn đề nghị người ta có thể đạt được điều này như thế nào? – Buhb

+0

Bạn về mặt lý thuyết có thể làm điều này với một số mâu thuẫn ClassLoader thủ công; khởi tạo các lớp từ A và B trong các trình nạp lớp riêng biệt, mà mỗi lớp chỉ có thể thấy phiên bản thư viện có liên quan. Trong thực tế điều này sẽ rất khó chịu để thực hiện và duy trì rằng nó không thực sự * khả thi *. –

+0

Tôi đã thực hiện nó một lần bằng cách sử dụng một plugin Maven, không chắc chắn nó là gì. Nó không phải là phức tạp để thực hiện, nhưng như tôi đã nói nó không được khuyến khích. Nó sẽ là một thảm họa cho các nhà phát triển sau khi bạn. – medopal