2013-01-15 32 views
10

Tôi đã cố tạo một chuỗi lớp tùy chỉnh trong gói java.lang trong không gian làm việc nhật thực của tôi. ban đầu tôi nghi ngờ rằng một lớp học tương tự trong cùng một gói không thể được tạo ra nhưng trước sự ngạc nhiên hoàn toàn của tôi, tôi đã có thể tạo ra một lớp (String) trong cùng một gói tức là java.langTạo chuỗi lớp tùy chỉnh

Bây giờ tôi bối rối
1) tại sao là nó có thể và
2) điều gì có thể là lý do nếu điều đó được cho phép.
3) những gì sẽ được sử dụng nếu loại này tạo ra các lớp java được cho phép trong Java.

+0

Nếu bộ nhớ phục vụ, 'cái gói java.lang' được [kín] (http://docs.oracle.com/javase/6/docs/technotes/ hướng dẫn/mở rộng/spec.html # niêm phong) để bạn không thể thêm thành viên vào nó. Tôi sẽ ngạc nhiên nếu thay thế kiểu 'String' mà không thực hiện nó trong jar thời gian chạy sẽ thành công với kiểu cơ bản của kiểu là hoạt động của JVM. – McDowell

Trả lời

9

Bạn có thể tạo một lớp mới trong gói java.lang. Nếu nó bị cấm như thế nào các nhà phát triển Oracle sẽ có thể phát triển Java ở tất cả? Tôi chắc chắn họ sử dụng cùng một javac như chúng tôi.

Nhưng bạn sẽ không thể tải nó, vì java.lang.ClassLoader (mà bất kỳ classloader kéo dài) không cho phép điều đó, mỗi lớp được nạp trải qua việc kiểm tra này

... 
     if ((name != null) && name.startsWith("java.")) { 
      throw new SecurityException 
       ("Prohibited package name: " + name.substring(0, name.lastIndexOf('.'))); 
     } 
... 

do đó bạn sẽ kết thúc trong một cái gì đó giống như

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang 
    at java.lang.ClassLoader.preDefineClass(ClassLoader.java:649) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:785) 
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) 
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
    at Test1.main(Test1.java:11) 

Đối với các lớp học bóng lớp hiện như java.lang.String của bạn không thể tải được vì Trình nạp Lớp Hệ thống (mặc định) sử dụng chiến lược "cha mẹ đầu tiên", vì vậy các lớp java.lang sẽ được tải từ rt.jar với trình nạp lớp bootstrap. Vì vậy, bạn sẽ cần phải thay thế String.class trong rt.jar bằng phiên bản của bạn. Hoặc ghi đè lên số sử dụng tùy chọn java -Xbootclasspath/p: để thêm đường dẫn vào đường dẫn tìm kiếm trình tải lớp khởi động. Vì vậy, bạn có thể

1) copypaste thực nội dung String.java vào String.java bạn

2) thay đổi một phương pháp, ví dụ như

public static String valueOf(double d) { 
    return "Hi"; 
} 

và biên dịch String.java bạn

3) tạo một lớp thử nghiệm

public class Test1 { 

    public static void main(String[] args) throws Exception { 
     System.out.println(String.valueOf(1.0d)); 
    } 
} 

4) chạy nó dưới dạng

java -Xbootclasspath/p:path_to_your_classes Test1 

và bạn sẽ thấy

Hi 
+1

Câu trả lời này trả lời 3 câu hỏi mà OP đã chỉ ra như thế nào? – SpaceTrucker

2

Có, bạn có thể tạo gói có tên java.lang và cũng được đặt tên là Chuỗi.

Nhưng bạn sẽ không thể chạy lớp Chuỗi của mình.

1) tại sao có thể: Trình biên dịch sẽ biên dịch thành công lớp học của bạn.

2) điều gì có thể là lý do nếu điều đó được cho phép: Bạn có tên hợp lệ cho gói và lớp của mình để trình biên dịch không phàn nàn.

3) điều gì sẽ được sử dụng nếu loại tạo lớp java này được cho phép trong Java: Nhưng không có nhiều sử dụng lớp String này. Trình nạp lớp Bootstrap sẽ tải lớp từ gói java.lang của mặt trời. Vì vậy, lớp Chuỗi tùy chỉnh của bạn sẽ không được tải và do đó nó không thành công trong khi chạy.

Trình tải lớp Bootstrap là một phần của việc triển khai JVM và nó tải các lớp Java API (bao gồm java.lang.String). Ngoài ra đối với mỗi lớp được tải, JVM theo dõi trình nạp lớp nào cho dù bootstrap hay do người dùng định nghĩa - đã nạp lớp đó. Vì vậy, bất kỳ nỗ lực nào để tải một lớp String tùy chỉnh sẽ không thành công khi lớp String đã được nạp.

+0

Bạn nên giải thích lý do tại sao anh ấy không thể chạy. – SpaceTrucker

+0

tôi nghĩ rằng tôi đã giải thích ... –

+0

cảm ơn rai.sKumar, nếu tôi wd đã có hai lựa chọn để chọn câu trả lời, tôi đã quyết định chọn đây là câu trả lời tốt thứ hai. Bởi vì nó rõ ràng, chính xác và đến mức trả lời. Nhưng câu trả lời được lựa chọn bởi Evgeniy Dorofeev là như vậy (bcoz code) ngay cả một layman có thể hiểu và mô phỏng vấn đề để giữ cho rằng trong tâm trí, tôi chọn câu trả lời của mình như là câu trả lời được chấp nhận, nhưng anyways rất rất cảm ơn :) –

4

Điều này được gọi là lớp bóng.

1.) Có thể vì các lớp java không được liên kết tĩnh, nhưng được liên kết ở thời gian tải lớp.

2.) Nếu nó không được phép, sau đó tải toàn bộ lớp sẽ khó khăn hơn nhiều để đạt được. Sau đó, ví dụ bạn cũng sẽ phải xây dựng dự án của bạn dựa trên một phiên bản Java cụ thể. vì các lớp Java có thể thay đổi từ phiên bản thành phiên bản. Đây không phải là cách tiếp cận có thể duy trì được.

3.) osgi sử dụng tính năng này để có thể tải các phiên bản khác nhau của cùng một gói. Một trường hợp sử dụng phổ biến khác là thay thế các lớp buggy trong các khung công tác, nơi không có cách giải quyết nào khác. Tuy nhiên kỹ thuật này nên được sử dụng cẩn thận, bởi vì các lỗi có thể khó gỡ lỗi.

Xin lưu ý rằng tuy nhiên, các lớp phủ bóng trong gói java. * Không được phép, vì điều này sẽ phá vỡ hộp cát bảo mật Java. Vì vậy, bạn sẽ có vấn đề trong thời gian chạy.