قبل بدء النص الرئيسي لهذه المقالة ، دعونا نلقي نظرة على الكود التالي:
دور integercache من فئة عدد صحيح في جافا
اسم الحزمة: java.lang
اسم الملف: integer.java
اسم الطريقة: integercache
رمز الطريقة كما يلي:
integercache integercache {static نهائي ثابت ؛ ذاكرة التخزين المؤقت الثابتة النهائية [] ؛ ثابت {Final int low = -128 ؛ // قد يتم تكوين قيمة عالية بواسطة الخاصية int h = 127 ؛ if (integerCacheHighpropValue! = null) {// استخدم long.decode هنا لتجنب استدعاء الطرق التي تتطلب ذاكرة التخزين المؤقت التلقائية الخاصة بـ integer int i = long.decode (integerCacheHhighpropValue) .intvalue () ؛ i = math.max (i ، 127) ؛ // الحد الأقصى لحجم الصفيف هو integer.max_value h = math.min (i ، integer.max_value - -low) ؛ } عالية = h ؛ ذاكرة التخزين المؤقت = عدد صحيح جديد [(ارتفاع - منخفض) + 1] ؛ int j = low ؛ لـ (int k = 0 ؛ k <cache.length ؛ k ++) ذاكرة التخزين المؤقت [k] = عدد صحيح جديد (j ++) ؛ } integercache () {}}نرى في الكود أن Low هو -128 و High هو 127. وبهذه الطريقة ، في برمجة Java ، إذا كنت ترغب في استخدام كائن في الفاصل الزمني -128-127 ، فسوف تستخدم الكائن مباشرة في هذه ذاكرة التخزين المؤقت.
ما سبق مقدمة موجزة لمساعدة الجميع على فهم integercache. ما يلي هو النص الرئيسي لهذه المقالة:
مقدمة
قبل 5 سنوات ، نشرت منشورًا عن الهنغارية حول كيفية تغيير IntegerCache في JDK. هذا النهج هو في الواقع التعمق في وقت تشغيل جافا ولا يستخدم فعليًا في السيناريوهات. عندما تقوم بتطوير رمز البحث هذا ، يمكنك أن تفهم بشكل أفضل كيف يعمل التفكير وكيف تنفذ فئة عدد صحيح.
تحتوي فئة Integer على integercache متداخلة خاصة ، والتي تحتوي على كائنات عدد صحيح مع قيم تتراوح من -127 إلى 128.
عندما يحتاج الرمز إلى إرفاق من النوع int إلى كائن عدد صحيح ، والقيمة ضمن هذا النطاق ، سيستخدم وقت تشغيل Java هذا ذاكرة التخزين المؤقت بدلاً من إنشاء كائن عدد صحيح جديد. هذا أساسا لاعتبارات تحسين الأداء. يجب أن نضع في اعتبارنا أن العديد من قيم INT غالبًا ما تكون ضمن هذا النطاق في البرنامج (مثل فهرس المُصنَّع للمصفوفة).
التأثير الجانبي لذلك هو أنه ، في كثير من الأحيان ، عند استخدام مشغل العلامات المتساوية لمقارنة كائنين عدد صحيح ، طالما كانت القيمة ضمن النطاق ، فهي صالحة. هذا نموذجي في اختبار الوحدة. في وضع التشغيل ، عندما تكون القيمة أكبر من 128 ، سيفشل تنفيذ الكود.
يمكن أن يؤدي استخدام انعكاس للوصول إلى فئات integercache إلى بعض الآثار الجانبية الغريبة ، لاحظ أن هذا يؤثر على JVM بأكمله. إذا أعادت Servlet تعريف قيمة ذاكرة التخزين المؤقت الدقيقة الصغيرة ، فإن جميع servlets الأخرى التي تعمل تحت نفس Tomcat تواجه نفس المشكلة.
هناك مقالات أخرى أعلاه في Lukas Eder و SitePoint.
الآن بعد أن ألعب مع الإصدارات المبكرة من Java 9 ، كل ما كان علي دائمًا القيام به في ذهني هو تجربة إصدارات Java الجديدة. قبل أن نبدأ ، دعونا نلقي نظرة على كيفية القيام بذلك في Java 8.
في مقالة لوكاس ، نشرت رمز نموذجه هنا:
استيراد java.lang.reflect.field ؛ استيراد java.util.random ؛ فئة عامة entropy {public static void main (string [] args) يلقي الاستثناء {// استخراج integercache من خلال فئة الانعكاس <<؟ > clazz = class.forname ("java.lang.integer $ integercache") ؛ حقل الحقل = clazz.getDeclaredField ("ذاكرة التخزين المؤقت") ؛ Field.SetAccessible (صحيح) ؛ integer [] cache = (integer []) field.get (clazz) ؛ // أعد كتابة ذاكرة التخزين المؤقت الصحيحة لـ (int i = 0 ؛ i <cache.length ؛ i ++) {cache [i] = new integer (new Random (). nextint (cache.length)) ؛ } // إثبات العشوائية لـ (int i = 0 ؛ i <10 ؛ i ++) {system.out.println ((integer) i) ؛ }}}يصل هذا الرمز إلى integercache من خلال الانعكاس ثم يستخدم قيمًا عشوائية لملء ذاكرة التخزين المؤقت (Naughty!).
نحاول تنفيذ نفس الرمز في Java 9 ، لا نتوقع أي متعة. عندما يحاول شخص ما انتهاكه ، سيجد أن Java 9 أكثر تقييدًا.
استثناء في الموضوع "Main" java.lang.reflect.inaccessibleObjectexception: غير قادر على جعل الحقل ثابتًا جافا.
يلقي البرنامج استثناء ، والذي لن يحدث في Java 8. إنه يعادل القول أن الكائنات لا تعتمد على النموذج. بسبب وحدة Java.base ، هذا جزء لا يتجزأ من JDK. يتم استيراده تلقائيًا عند بدء كل برنامج Java ، ولا يُسمح بفتح الوحدات النمطية التي لم يكشف عن اسمها. يتم طرح هذا الاستثناء عندما نحاول تعيين خاصية يمكن الوصول إليها الحقل.
لا يمكن الوصول إلى الكائنات التي يمكننا الوصول إليها بسهولة في Java 8 في Java 9 لأن نظام الوحدة النمطية الجديدة يحمي هذا. لا يمكن للرمز الوصول إلى الحقول والأساليب والمعلومات الأخرى التي يمكن الوصول إليها عن طريق التفكير ، إلا إذا كانت الفئة في نفس الوحدة ، أو أن الوحدة النمطية تفتح حزمة للوصول إلى الانعكاس. يمكن تنفيذ ذلك من خلال ملف تعريف الوحدة النمطية للوحدة النمطية:
وحدة myModule {orports com.javax0.module.demo ؛ يفتح com.javax0.module.demo ؛} هذه الوحدة النمطية java.base ليست ضرورية لفتحها من تلقاء نفسها للوصول إلى الانعكاس ، خاصة بالنسبة للوحدات النمطية التي لم يكشف عن اسمها. إذا قمت بإنشاء وحدة نمطية وتسميتها ، فسوف تحتوي رسالة الخطأ على اسم الوحدة النمطية.
هل يمكننا فتح الوحدات النمطية في البرنامج؟ تحتوي وحدة java.lang.reflect.Module على طريقة AddOpens التي يمكن القيام بها.
هل هو ممكن؟
الأخبار السيئة للمطورين هي: إنها ليست ممكنة. يمكنه فتح حزمة فقط في وحدة نمطية في وحدة أخرى ، وتم فتح الحزمة في تلك الوحدة عن طريق استدعاء هذه الطريقة. يمكن أن تسمح هذه الطريقة فقط بتمرير الوحدات النمطية إلى حقوق وحدة أخرى ، شريطة أن تكون الوحدة الأخرى قد فتحت نفس الحزمة بطريقة ما ، ولا يمكنها فتح الحزم غير المفتوحة (ملاحظة المترجم: من الصعب فهمها ، أليس كذلك؟).
ولكن في الوقت نفسه ، فإن الأخبار السارة هي: Java 9 ليس من السهل كسر Java 8. على الأقل تم إغلاق هذه الثغرة الأمنية. يبدو أن جافا بدأت في التطور نحو المستوى المهني ، وليس مجرد لعبة (ملاحظة المترجم: من قال إن جافا هي لعبة؟). في المستقبل القريب ، يمكنك ترحيل المشاريع في لغات آر بي جي وكوبول إلى جافا على محمل الجد. (آسف ، كنت أمزح)
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.
يتم ترجمة هذه المقالة من: https://dzone.com/articles/hacking-the-integercache-in-java-9