2008-09-20 22 views
5

Tôi có một chương trình Java tải các tệp lớp của bên thứ ba (các lớp tôi không viết) và thực thi chúng. Các lớp này thường sử dụng java.util.Random, theo mặc định, tạo ra các giá trị hạt giống bắt đầu ngẫu nhiên mỗi khi nó được khởi tạo. Vì lý do tái tạo, tôi muốn cho các lớp này cùng một hạt giống bắt đầu mỗi lần, thay đổi nó theo quyết định của tôi.Làm thế nào tôi có thể cho java.util.Random một hạt giống cụ thể trong các lớp học của bên thứ ba?

Dưới đây là một số trong những giải pháp rõ ràng, và tại sao họ không làm việc:

  1. Sử dụng một lớp ngẫu nhiên khác nhau trong classfiles thirdparty. Vấn đề ở đây là tôi chỉ tải các tệp lớp và không thể sửa đổi nguồn.

  2. Sử dụng trình nạp lớp tùy chỉnh để tải lớp ngẫu nhiên của riêng chúng tôi thay vì phiên bản của JVM. Cách tiếp cận này sẽ không hoạt động vì Java không cho phép các trình nạp lớp ghi đè lên các lớp trong gói java.

  3. Hoán đổi bản thực thi java.util.Random của rt.jar cho riêng chúng tôi hoặc đưa tệp vào vị trí đáng tin cậy cho JVM. Các phương pháp này yêu cầu người dùng ứng dụng rối tung với cài đặt JVM trên máy của họ và không tốt.

  4. Thêm lớp tùy chỉnh java.util.Random vào lớp khởi động. Trong khi điều này sẽ làm việc về mặt kỹ thuật, đối với ứng dụng cụ thể này, nó là không thực tế bởi vì ứng dụng này là dành cho người dùng cuối để chạy từ một IDE. Tôi muốn làm cho ứng dụng chạy thuận tiện cho người dùng, có nghĩa là buộc họ phải đặt bootclasspath của họ là một nỗi đau. Tôi không thể giấu điều này trong một kịch bản, vì nó được dự định chạy từ một IDE như Eclipse (để gỡ lỗi dễ dàng.)

Vậy làm cách nào tôi có thể làm điều này?

Trả lời

2

Xem xét sửa đổi thư viện của bên thứ ba để họ sử dụng thông báo cho các trường hợp ngẫu nhiên của họ. Mặc dù bạn không có mã nguồn, bạn có thể chỉnh sửa bytecode để làm điều đó. Một bộ công cụ hữu ích để làm như vậy là ASM.

1

Bạn có thể sử dụng AOP để chặn các cuộc gọi đến Ngẫu nhiên và xoay vòng arg theo ý bạn muốn.

Sam

0

"Sử dụng một classloader tùy chỉnh để tải lớp ngẫu nhiên của chúng ta thay vì phiên bản của JVM. Cách tiếp cận này sẽ không làm việc vì Java không cho phép classloaders để ghi đè lên lớp trong gói java."

cách thay đổi bootclasspath để sử dụng lớp Random tùy chỉnh của bạn?

BR, ~ Một

+0

Cha Nging bootclasspath có hiệu quả, nhưng đòi hỏi phải sửa đổi cách chương trình Java được chạy. Điều này là tốt nếu bạn có thể kiểm soát cách ai đó khởi chạy chương trình, ví dụ: một kịch bản khởi động, nhưng trong trường hợp của tôi, người dùng thường chạy từ bên trong một IDE và sẽ phải thực hiện nó theo cách thủ công, điều đó không tốt. – adum

1

Mặc dù bạn có thể không thay đổi classloader trivially cho "java.x" và gói "sun.x", có một cách để nghĩ lớp tải (và cài đặt một "sau giờ học được bytecoded và nạp "listener) của các lớp học, vì vậy bạn có thể thiết lập một cái gì đó giống như hạt giống sau khi tải các lớp học từ các gói này. Gợi ý: Sử dụng sự phản chiếu.

Dù sao, miễn là tôi không có thêm thông tin chính xác những gì bạn muốn đạt được, thật khó để giúp bạn ở đây.

P .: hãy lưu ý rằng "tĩnh {}" - các khối có thể cản trở bạn rối tung xung quanh với hạt giống, một lần nữa.

3

Tùy chọn 2 của bạn sẽ thực sự hoạt động, với các hướng dẫn sau.

Bạn sẽ cần (như anjab đã nói) để thay đổi đường dẫn lớp khởi động.

Trong dòng lệnh của chương trình bạn cần phải thêm những điều sau đây:

java -Xbootclasspath/p: C: \ của bạn \ random_impl.jar YourProgram

Giả sử bạn đang ở trên máy Windown hoặc đường dẫn cho vấn đề đó trong bất kỳ hệ điều hành nào.

Tùy chọn đó thêm các lớp trong tệp jar trước khi tệp rt.jar được tải. Vì vậy, Random của bạn sẽ được tải trước khi lớp ngẫu nhiên rt.jar làm.

Việc sử dụng sẽ được hiển thị bằng cách gõ:

java -X 

Nó hiển thị tất cả các X (tra) tính năng de JVM có. Nó có thể không có sẵn trên các triển khai VM khác như JRockit hoặc khác nhưng nó có trên Sun JVM.

-Xbootclasspath/p: thêm vào trước ở phía trước đường dẫn lớp bootstrap

Tôi đã sử dụng phương pháp này trong một ứng dụng mà lớp ORB mặc định nên được thay thế bằng những người khác Orb thực hiện. Lớp ORB là một phần của Java Core và không bao giờ có bất kỳ vấn đề gì.

Chúc may mắn.

0

Có phương án 2 là làm việc: tạo ra hai lớp dành cho mục đích thử nghiệm tên ThirdPartyClass.javaRandom.java

tạo jar từ ThirdPartyClass.class

jar -cvf tpc.jar ThirdPartyClass.class 

tạo jar từ Random.class

jar -cvf rt123.jar Random.class 

sau đó thực hiện với lệnh sau:

java -Xbootclasspath/p:tcp.jar:rt123.jar -cp . -verbose ThirdPartyClass 

Đầu ra sẽ là: Mã seed value for ThirdPartyClass-> 1

nguồn ThirdPartyClass.java -----> Random.java đang

import java.util.Random; 

public class ThirdPartyClass { 
    ThirdPartyClass(long seed) { 
     System.out.println("seed value for ThirdPartyClass-> "+seed); 
    } 

    public static void main(String [] args) { 
     ThirdPartyClass tpc=new ThirdPartyClass(new Random().nextLong()); 
    } 
} 

nguồn ------->

package java.util; 

import java.io.Serializable; 

public class Random extends Object implements Serializable 
{ 
    public Random() { 
    } 

    public Random(long seed) { 
    } 

    public long nextLong() { 
     return 1; 
    } 
} 

Cảm ơn Mahaveer Prasad Mali

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