2010-12-29 27 views
52

Giả sử chúng ta có một chương trình Java tầm thường mà bao gồm chỉ là một lớp:Thay đổi phương pháp khi chạy qua một cơ chế trao đổi nóng

public class HelloWorld { 

    private static void replacable(int i) { 
     System.out.println("Today is a nice day with a number " + i); 
    }   

    public static void main(String[] args) throws Exception { 
     for(int i = 0; i < 100000; ++i) { 
     replacable(i); 
     Thread.sleep(500); 
    } 
} 

Sau khi nó được biên dịch và chạy, đầu ra sẽ là thế này:

Hôm nay là một ngày tốt đẹp với một số 0

Hôm nay là một ngày tốt đẹp với một số 1

Hôm nay là một ngày tốt đẹp với một số 2

Hôm nay là một ngày tốt đẹp với một số 3

...

Câu hỏi của tôi: không có tồn tại (hoặc là có trên đường chân trời) một cách nào đó để trao đổi replacable phương pháp trong thời gian chạy? Một cái gì đó như viết một phiên bản khác của HelloWorld với một phiên bản mới của replacable, biên dịch nó và sau đó là phiên bản cũ trong một JVM đã chạy?

Vì vậy, nếu tôi viết phiên bản mới như thế này:

private static void replacable(int i) { 
    System.out.println("Today is an even nicer day with a number " + i); 
} 

là có một cái gì đó tương tự như Erlang's hot code swapping nơi tôi có thể làm điều này:

  1. chạy chương trình gốc
  2. ghi sửa đổi phiên bản
  3. bằng chương trình dòng lệnh, kết nối với JVM đang chạy và thay thế phương thức hiện tại

do đó, trong thời gian chạy, điều này sẽ xảy ra:

Hôm nay là một ngày tốt đẹp với một số 15000

Hôm nay là một ngày tốt đẹp với một số 15001

Hôm nay là một thậm chí ngày đẹp hơn với số 15002

Hôm nay là một ngày đẹp hơn với số 15003

...

Giả sử rằng chương trình trên là độc lập, chạy trong môi trường Java SE chuẩn, không có gì khác trên classpath, vì vậy nó gần như là một chương trình kiểu thế giới Hello.

Lưu ý: Tôi biết rằng các công nghệ như thao tác bytecode (cglib), aspectJ, jRebel, JMX, hotswapping các phương pháp trong Java EE, vv tồn tại, nhưng chúng không phải là những gì tôi đang nghĩ đến việc. Hãy suy nghĩ về Erlang.

+3

Bạn có thể giải thích lý do tại sao bạn không thể sử dụng Mẫu chiến lược (ví dụ: một đối tượng biến thực hiện chức năng biến bắt buộc) không? Các phương thức hoán đổi âm thanh phức tạp để đạt được những gì bạn muốn. – ivy

+0

@ivy: Tôi có thể sử dụng điều đó, tất nhiên, nhưng tôi chỉ tự hỏi liệu có thể làm những gì tôi mô tả trong câu hỏi của mình hay không. Bạn có thể nghĩ nó như một câu hỏi "lý thuyết" theo một cách nào đó. – darioo

+0

@ivy cơ chế có để nâng cấp dịch vụ đang chạy, không phải để chọn giữa một tập hợp các triển khai đã biết. –

Trả lời

35

Bạn có thể sử dụng mã nguồn mở HotSpot VM hoặc plugin thương mại JRebel IDE để dễ dàng đạt được mục tiêu của mình (xem bảng so sánh here).

+0

là điều này mạnh mẽ và phù hợp với môi trường sản xuất? Như trong, nâng cấp nóng cho các dịch vụ đang chạy mà không có thời gian chết? Hoặc là nó thực sự chỉ là một cách để rút ngắn một chu trình chỉnh sửa/biên dịch/chạy trong dev? – Kevin

+0

Không - nó không thích hợp để sản xuất – IcedDante

3

Bạn có thể làm điều này thông qua việc JPDA (Java Platform Debugger Kiến trúc) giao diện: http://download.oracle.com/javase/1.4.2/docs/guide/jpda/enhancements.html#hotswap

Nó không tự động theo từng trường hợp Erlang - JVM không giám sát các đường dẫn lớp để thay đổi các tập tin lớp sau đó tải lại và liên kết lại nếu chúng thay đổi, vì những lý do khá rõ ràng (Java được thiết kế để triển khai web bạn không muốn bỏ phiếu cho một URL http để thay đổi).

+0

Tôi sẽ dùng thử JPDA một ngày. Những gì tôi có trong tâm trí đã được đảo ngược.JVM không giám sát các thay đổi tệp lớp, nhưng bạn giao cho JVM đang chạy trực tiếp phiên bản "mới" của một lớp. – darioo

14

Bạn có thể thực hiện việc này thông qua trình tải lớp. Ví dụ nếu bạn đã quen thuộc với các thùng chứa Servlet như tomcat tải lại các trang khi bạn sửa đổi chúng trong quá trình phát triển. Đây là great explanation of creating dynamic code in java. Nó không chỉ giải thích tải mà còn biên dịch nguồn trên bay. Bạn sẽ có thể áp dụng các khái niệm được bảo hiểm cho bất kỳ chiến lược tải lại mã nào bạn muốn sử dụng.

9

Tôi đã sử dụng số hotswap ant task này trong nhiều dự án. Ứng dụng java mục tiêu có thể được đưa ra thông qua Ant, Eclipse, một dấu nhắc lệnh hoặc bất kỳ phương tiện nào khác miễn là nó được khởi chạy trong chế độ gỡ lỗi với cổng thích hợp mở. Trang được liên kết cung cấp hướng dẫn về cách thực hiện điều này thông qua Ant.

Bất kỳ số lượng lớp nào cũng có thể được thay thế miễn là các thay đổi không phải là cấu trúc. Phương pháp thay đổi cơ thể thường là hotswap một cách dễ dàng. Mã có thể được thay thế bằng cách chạy một kịch bản kiến ​​thông qua một trình bao hoặc Eclipse.

Tại nơi làm việc, tôi sử dụng tập lệnh tự động thay đổi mã tự động bằng cách so sánh dấu thời gian trên tệp lớp. Điều này tương tự như mẫu trên trang dự án cho thấy một ví dụ đơn giản chỉ có các hotswaps thay đổi các lớp.

Lưu ý bổ sung: Điều này sử dụng JPDA.

+0

Plus 1 vì bạn đề cập đến JPDA, đây là giao diện JVM thực tế được các công cụ sử dụng. Bây giờ tôi chỉ muốn xem một ví dụ runnable tối thiểu :-) –

2

Còn OSGi thì sao? Trao đổi nóng là sorta "được xây dựng trong" để spec - Tôi sẽ nghĩ rằng đây sẽ là một trong những giải pháp có thể là tốt.

2

Bạn có thể sử dụng mẫu thiết kế Chiến lược, vì vậy bạn có một đối tượng để thao tác thay vì phương thức và giao thức để giao tiếp với chương trình để cho nó sử dụng tên lớp đã cho làm lớp của đối tượng Chiến lược.

4

Một bài hơi cũ, nhưng hy vọng ai đó sẽ tìm thấy hữu ích này:

Tôi đã tìm thấy tương đối mới hơn Hotswap Agent cũng là tài liệu và tính năng phong phú (và tốt nhất của tất cả, open source).

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