في برمجة Java التقليدية، لن تحتاج بعد الآن إلى التعامل مع كائنات Java أو مواقعها من الذاكرة. عند مناقشة هذا الأمر في المنتديات، فإن السؤال الأول الذي يطرح نفسه هو لماذا تحتاج إلى معرفة عنوان كائن Java؟ إنه سؤال صحيح. لكن في الماضي كنا نحتفظ بالحق في إجراء المحاكمات. لا حرج في استكشاف الأسئلة في منطقة مجهولة. توصلت إلى تجربة باستخدام باقات شركة الشمس. غير آمنة هي حزمة تابعة لsun.misc. ربما تكون هذه الحزمة غير مألوفة بعض الشيء بالنسبة لك، ألقِ نظرة على الكود المصدري والطرق، وستعرف ما أشير إليه.
توفر إدارة أمان Java ما يكفي من الإخفاء لضمان عدم إمكانية العبث بالذاكرة بهذه السهولة. كخطوة أولى، فكرت في الحصول على موقع الذاكرة لكائن Java. حتى الاستكشاف، كنت واثقًا بنسبة 100% من أنه من المستحيل العثور على موقع عنوان كائن ما في Java.
تُظهر وثائق Unsafe.java API الخاصة بشركة Sun أن لدينا إمكانية الوصول إلى العنوان باستخدام الأسلوب objectFieldOffset. يبدو أن هذه الطريقة تقول: "يخصص الفصل الموجود في التقرير موقعه في منطقة تخزين معينة." ويقول أيضًا: "هذا مجرد موصل حيث يتم تمرير ملف تعريف الارتباط إلى ذاكرة كومة غير آمنة." على أي حال، أنا قادر على تخصيص موقع الذاكرة حيث يتم تخزين الكائن من مساحة تخزين فئته. يمكنك القول بأن ما نحصل عليه ليس عنوان الذاكرة الفعلية المطلقة لكائن ما. ومع ذلك، حصلنا على عنوان الذاكرة المنطقية. البرنامج التالي سيكون ذو فائدة كبيرة لك!
كخطوة أولى، لا بد لي من الحصول على كائن من فئة غير آمنة. وهذا أمر صعب لأن شركات البناء خاصة. هناك طريقة تسمى getUnsafe والتي تقوم بإرجاع كائن غير آمن. تتطلب إدارة أمان Java منح امتيازات التعليمات البرمجية المصدر. لقد استخدمت القليل من التفكير وحصلت على مثال. أعلم أن هناك طرقًا أفضل للحصول على مثيل، لكنني اخترت الطريقة التالية لتجاوز إدارة الأمان.
لاستخدام الكائنات غير الآمنة، ما عليك سوى استدعاء objectFieldOffset وstaticFieldOffset. والنتيجة هي عنوان تخصيص الذاكرة للفئة.
يمكن تشغيل البرنامج المثال التالي على JDK1.6.
موقع الكائن من الفئة العامة {
التفاحة الثابتة الخاصة = 10 ؛
برتقالي خاص = 10 ؛
public static void main(String[] args) يطرح الاستثناء {
Unsafe unsafe = getUnsafeInstance();
الحقل appleField = ObjectLocation.class.getDeclaredField("apple");
System.out.println("موقع Apple:"
+ unsafe.staticFieldOffset(appleField));
الحقل orangeField = ObjectLocation.class.getDeclaredField("orange");
System.out.println("موقع البرتقالة:"
+ unsafe.objectFieldOffset(orangeField));
}
getUnsafeInstance () الثابت الخاص غير الآمن يطرح SecurityException،
NoSuchFieldException، IllegalArgumentException،
استثناء الوصول غير القانوني {
حقل theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}