ในการเขียนโปรแกรม Java แบบเดิม คุณไม่จำเป็นต้องจัดการกับอ็อบเจ็กต์ Java หรือตำแหน่งจากหน่วยความจำอีกต่อไป เมื่อคุณพูดคุยเรื่องนี้ในฟอรั่ม คำถามแรกที่ผุดขึ้นมาคือทำไมคุณต้องรู้ที่อยู่ของวัตถุ Java? มันเป็นคำถามที่ถูกต้อง แต่ที่ผ่านมาเราขอสงวนสิทธิ์ในการดำเนินการทดลอง ไม่มีอะไรผิดปกติกับการสำรวจคำถามในดินแดนที่ไม่จดที่แผนที่ ฉันเกิดการทดลองโดยใช้แพ็คเกจของบริษัทซัน Unsafe เป็นแพ็คเกจที่เป็นของ sun.misc บางทีแพ็คเกจนี้อาจไม่คุ้นเคยสำหรับคุณ ลองดูที่ซอร์สโค้ดและวิธีการแล้วคุณจะรู้ว่าฉันหมายถึงอะไร
การจัดการความปลอดภัยของ Java ให้การซ่อนที่เพียงพอเพื่อให้แน่ใจว่าคุณจะไม่ยุ่งกับหน่วยความจำได้อย่างง่ายดาย ในขั้นตอนแรก ฉันคิดว่าจะต้องรับตำแหน่งหน่วยความจำของวัตถุ Java จนกระทั่งสำรวจ ฉันเคยมั่นใจ 100% ว่าเป็นไปไม่ได้ที่จะค้นหาตำแหน่งของที่อยู่ของวัตถุใน Java
เอกสาร Unsafe.java API ของ Sun แสดงให้เห็นว่าเราสามารถเข้าถึงที่อยู่โดยใช้เมธอด objectFieldOffset ดูเหมือนว่าวิธีนี้จะพูดว่า "คลาสในรายงานจัดสรรตำแหน่งในพื้นที่เก็บข้อมูลเฉพาะ" นอกจากนี้ยังระบุด้วยว่า "นี่เป็นเพียงตัวเข้าถึงที่คุกกี้ถูกส่งผ่านไปยังหน่วยความจำฮีปที่ไม่ปลอดภัย" อย่างไรก็ตาม ฉันสามารถจัดสรรตำแหน่งหน่วยความจำที่เก็บอ็อบเจ็กต์จากที่เก็บข้อมูลของคลาสได้ คุณสามารถโต้แย้งได้ว่าสิ่งที่เราได้รับไม่ใช่ที่อยู่หน่วยความจำกายภาพสัมบูรณ์ของวัตถุ อย่างไรก็ตาม เราได้รับที่อยู่หน่วยความจำลอจิคัลแล้ว โปรแกรมต่อไปนี้จะเป็นประโยชน์กับคุณอย่างมาก!
ในขั้นตอนแรก ฉันต้องได้รับอ็อบเจ็กต์ของคลาส Unsafe นี่เป็นเรื่องยากเพราะตัวสร้างเป็นแบบส่วนตัว มีวิธีที่เรียกว่า getUnsafe ซึ่งส่งคืนวัตถุที่ไม่ปลอดภัย การจัดการความปลอดภัยของ Java ต้องการให้คุณให้สิทธิ์ซอร์สโค้ด ฉันใช้การสะท้อนเล็กน้อยและได้รับตัวอย่าง ฉันรู้ว่ามีวิธีที่ดีกว่าในการรับอินสแตนซ์ แต่ฉันเลือกวิธีต่อไปนี้เพื่อหลีกเลี่ยงการจัดการความปลอดภัย
หากต้องการใช้วัตถุที่ไม่ปลอดภัย เพียงเรียก objectFieldOffset และ staticFieldOffset ผลลัพธ์คือที่อยู่การจัดสรรหน่วยความจำของชั้นเรียน
โปรแกรมตัวอย่างต่อไปนี้สามารถทำงานบน JDK1.6
ObjectLocation ระดับสาธารณะ {
int apple ส่วนตัวคงที่ = 10;
ส่วนตัว int สีส้ม = 10;
โมฆะคงที่สาธารณะ main (String [] args) พ่นข้อยกเว้น {
ไม่ปลอดภัย ไม่ปลอดภัย = getUnsafeInstance();
ฟิลด์ appleField = ObjectLocation.class.getDeclaredField("apple");
System.out.println("ตำแหน่งของ Apple: "
+ unsafe.staticFieldOffset(appleField));
ฟิลด์ orangeField = ObjectLocation.class.getDeclaredField("สีส้ม");
System.out.println("ตำแหน่งของสีส้ม: "
+ unsafe.objectFieldOffset(orangeField));
-
ส่วนตัวคงที่ Unsafe getUnsafeInstance() พ่น SecurityException
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
ฟิลด์ theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(จริง);
กลับ (ไม่ปลอดภัย) theUnsafeInstance.get (Unsafe.class);
-
-