2008-11-14 15 views
14

Tôi đã thực sự xem xét sự khác biệt giữa truyền theo giá trị và cách Java phân bổ các đối tượng và java làm gì để đặt các đối tượng trên ngăn xếp.Câu hỏi chung: Java có chồng và ngăn xếp cục bộ. Bạn có thể truy cập bất kỳ đối tượng nào từ heap không?

Có cách nào để truy cập các đối tượng được phân bổ trên heap không? Cơ chế nào thực thi java để đảm bảo rằng phương thức đúng có thể truy cập đúng dữ liệu ngoài heap?

Dường như nếu bạn xảo quyệt và thậm chí có thể thao túng bytecode java trong thời gian chạy, bạn có thể thao tác dữ liệu khỏi heap khi bạn không được phép?

+1

Câu hỏi hay - Tôi ước mình biết thêm về java; một câu trả lời tốt cho điều này sẽ là một sự khởi đầu cho sự giác ngộ của tôi :) –

Trả lời

17

Không có hướng dẫn trong tập lệnh JVM cho phép truy cập tùy ý vào vùng heap. Do đó, thao tác bytecode sẽ không giúp bạn ở đây.

JVM cũng có trình xác minh. Nó kiểm tra mã của mọi phương thức (như một lớp đang được nạp) để xác minh rằng phương thức này không cố gắng để bật nhiều giá trị hơn so với những gì nó đã đẩy lên nó. Điều này đảm bảo rằng một phương thức không thể "nhìn thấy" các đối tượng được chỉ ra bởi phương thức gọi của nó.

Cuối cùng, các biến cục bộ được lưu trữ trong một mảng mỗi phương thức (được gọi là "mảng biến cục bộ"). Một lần nữa, trình xác minh đảm bảo rằng mọi lệnh đọc/ghi từ/đến - mảng đó chỉ định một chỉ mục nhỏ hơn kích thước của mảng. Lưu ý rằng các lệnh JVM này chỉ có thể chỉ định một chỉ mục hằng số. Họ không thể lấy một giá trị tính toán và sử dụng nó như một chỉ mục.

Vì vậy, để tóm tắt, câu trả lời là số

+0

Tôi vừa trở lại với điều này. Vì vậy, về cơ bản cấu trúc của Java và thu thập rác tương tự, các ngôn ngữ dựa trên ngăn xếp là như vậy mà bạn không thể tự ý truy cập vào một phần của heap khi bạn không có acces để làm như vậy. –

9

Tất cả các đối tượng trong Java đều nằm trên heap. Tôi không hoàn toàn chắc chắn những gì bạn có nghĩa là "truy cập các đối tượng từ đống". Những thứ duy nhất được lưu trữ trên stack là danh sách các hàm được gọi vào ngữ cảnh hiện tại và các biến và tham số cục bộ của chúng. Tất cả các biến và tham số cục bộ là các kiểu hoặc tham chiếu nguyên thủy.

Nếu bạn phân bổ một đối tượng bằng cách sử dụng new (là cách duy nhất để phân bổ các kiểu không nguyên thủy; có điều này bao gồm các loại mảng), thì đối tượng được cấp phát trên heap và tham chiếu đến đối tượng đó được lưu trữ trên stack hoặc heap, tùy thuộc vào nếu tham chiếu được lưu trữ trong một biến địa phương/tham số hoặc là một thành viên của đối tượng khác.

Khi được chuyển thành tham số cho hàm, tất cả đối tượng được truyền theo tham chiếu - nếu hàm sửa đổi tham số, đối tượng gốc cũng được sửa đổi. Về cơ bản, người ta cũng có thể nói rằng các tham chiếu đối tượng được truyền theo giá trị - nếu bạn thay đổi một tham số để chỉ một đối tượng mới, nó sẽ tiếp tục tham chiếu đến đối tượng đó trong suốt thời gian của hàm, nhưng đối tượng ban đầu được truyền vào vẫn sẽ đề cập đến bất cứ điều gì nó đã nói đến trước đây. Các kiểu nguyên thủy cũng được truyền theo giá trị.

+0

Có nhiều cách khác để phân bổ các đối tượng mới (clone, Class.newInstance(), deserialization), nhưng tất cả chúng đều kết thúc trên heap. –

+4

"Người ta cũng có thể nói rằng tham chiếu đối tượng được truyền theo giá trị" giải thích là chỉ chính xác.Nói rằng các đối tượng được truyền qua tham chiếu là không chính xác. Về cơ bản Java chỉ có giá trị vượt qua, như C. –

4

Về đối tượng trên stack, nó chỉ mới Java 6 VM từ SUN (và có lẽ một số người khác) mà sẽ cố gắng để tối ưu hóa mã byte bằng cách đặt các đối tượng trên ngăn xếp. Thông thường, tất cả các đối tượng sẽ đi vào heap. Để tham khảo, hãy xem: http://www.ibm.com/developerworks/java/library/j-jtp09275.html

Thông số JVM cũng ở số http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#6348. JVM bảo vệ đống của nó bằng cách đơn giản là không cung cấp cho bạn các hướng dẫn cần thiết để làm hỏng nó. Các lỗi trong triển khai JVM có thể làm cho số dặm của bạn thay đổi.

+0

Tôi không đồng ý với các bình luận Java 6. Tính năng mới của phân tích thoát có khả năng cho phép JVM tránh việc tạo ra các đối tượng. Vì vậy, các thành phần nguyên thủy của những gì sẽ có được các đối tượng (int, float, tài liệu tham khảo, vv) kết thúc trên stack. Đối tượng chỉ tồn tại trong heap. Giai đoạn. –

+1

Một trang IBM khác, http://www.ibm.com/developerworks/library/j-jtp01274.html, không đồng ý với bạn John M. Có vẻ như Java thực sự có thể phân bổ các đối tượng trên ngăn xếp. –

+0

@StevenSchlansker link down .. – Pacerier

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