مقدمة
تقدم هذه المقالة بشكل أساسي المحتوى ذي الصلة حول الفصل غير الآمن في Java. يتم مشاركته للرجوع إليه وتعلمك. لن أقول الكثير أدناه. دعونا نلقي نظرة على المقدمة التفصيلية معًا.
1. مقدمة فئة غير آمنة
تقع الفئة غير الآمنة تحت حزمة Sun.Misc ولا تنتمي إلى معيار Java. ومع ذلك ، يتم تطوير العديد من مكتبات فئة Java Basic ، بما في ذلك بعض مكتبات التطوير عالية الأداء المستخدمة على نطاق واسع ، بناءً على فئة غير آمنة ، مثل Netty ، Hadoop ، Kafka ، إلخ.
يمكن استخدام غير آمن للوصول مباشرة إلى موارد ذاكرة النظام والإدارة بشكل مستقل. تلعب الفئة غير الآمنة دورًا رائعًا في تحسين كفاءة تشغيل Java وتعزيز قدرات التشغيل الأساسية للغة Java.
يمكن اعتبار غير آمن الباب الخلفي المتبقي في جافا ، مما يوفر بعض العمليات منخفضة المستوى ، مثل الوصول المباشر للذاكرة ، وجدولة مؤشرات الترابط ، إلخ.
لا ينصح غير آمن.
فيما يلي بعض الأمثلة على استخدام غير آمن.
1.1 إنشاء فئة خاصة
استيراد java.lang.reflect.field ؛ استيراد sun.misc.unsafe ؛ فئة عامة غير مستحيلة {public static void main (string [] args) يلقي استثناء {// instantiate field unsafe f = unsafe.class.getDeclaredfield ("theunsafe") ؛ F.SetAccessible (صحيح) ؛ غير آمن غير آمن = (غير آمن) f.get (null) ؛ // Instantiate Player Player = (player) unfafe.allocateinstance (player.class) ؛ player.setName ("li lei") ؛ System.out.println (player.getName ()) ؛ }} player {private string name ؛ player player () {} السلسلة العامة getName () {return name ؛ } public void setName (اسم السلسلة) {this.name = name ؛ }} التشغيل 1.2cas ، قم بتغيير قيمة العداد من خلال تعديل عنوان إزاحة الذاكرة
استخدم CAS لتحديث الجزء العلوي من المكدس في TransferStack في حزمة Concurrency Java.
/ غير آمن Mechanicsprivate static Final Sun.Misc.unsafe غير آمن ؛ headoffset نهائي ثابت طويل ؛ ثابت {try {unsafe = sun.misc.unsafe.getunsafe () ؛ الفئة <؟> k = transferstack.class ؛ Headoffset = unfafe.ObjectFieldOffset (K.GetDeclaredField ("Head")) ؛ } catch (استثناء e) {رمي خطأ جديد (e) ؛ }} // volatile snode head ؛ // قم بتحديث الجزء العلوي من المكدس boolean cashead (snode h ، snode nh) {return h == head && unfafe.compareanswapobject (this ، headoffset ، h ، nh) ؛} 1.3 الوصول المباشر للذاكرة
الوصول المباشر للذاكرة غير الآمن: لا تشغل مساحة الذاكرة المفتوحة مع Unfae مساحة كومة ، وبالطبع لا تحتوي على وظيفة استرداد الذاكرة التلقائي. جعل من الممكن استخدام موارد ذاكرة النظام بحرية مثل C.
2. تحليل رمز مصدر الفئة غير الآمن
معظم واجهات برمجة التطبيقات الخاصة بـ Unsafe هي الأساليب الأصلية ، بما في ذلك الفئات التالية:
1) الفئة ذات الصلة. يوفر بشكل أساسي أساليب تشغيل الحقول الثابتة وحقولها.
2) الكائن المتعلق. يوفر بشكل أساسي طرق تشغيل الكائن وحقوله.
3) Arrray ذات الصلة. يوفر بشكل أساسي طرق تشغيل المصفوفات والعناصر فيها.
4) الارتباط المتزامن. إنه يوفر بشكل أساسي بدائل التزامن منخفض المستوى ، مثل CAS ، جدولة الخيوط ، المتطايرة ، حاجز الذاكرة ، إلخ.
5) ذات الصلة بالذاكرة. يوفر طريقة وصول للذاكرة مباشرة (تجاوز كومة Java ومعالجة الذاكرة المحلية مباشرة) ، والتي يمكنها الاستفادة بحرية موارد ذاكرة النظام مثل C.
6) النظام المتعلق. إنه يعيد بشكل أساسي بعض معلومات الذاكرة ذات المستوى المنخفض ، مثل حجم العنوان وحجم صفحة الذاكرة.
2.1class ذات الصلة
// يتم استخدام إزاحة السمات الثابتة لقراءة وكتابة سمات ثابتة في كائن الفئة المقابل العام الطويل Staticfieldoffset (الحقل F) ؛ الكائن الأصلي العام staticfieldbase (الحقل f) ؛ // الحكم على ما إذا كان يجب أن يتم تهيئة الطبقة العامة المنطقية الأصلية (الفئة <؟> C) ؛ // تأكد Loader ، ProtectDomain Protectomain) ؛ // تحديد فئة مجهولة يمكن استخدامها لإنشاء فئات عامة فئة عامة <؟> defineanonymousClass (الفئة <؟> HostClass ، Byte [] البيانات ، الكائن []
2.2Object المرتبطة
هناك الطرق التالية للأنواع الأساسية (Boolean ، Byte ، Char ، Short ، int ، Long ، تعويم ، مزدوجة) وأنواع مرجعية للكائنات في Java.
// احصل على إزاحة حقل الكائن العام الطويل الكائن الطويل (الحقل F) ؛ // احصل على قيمة int لعنوان الكائن المحدد إزاحة عامة int getint (الكائن O ، إزاحة طويلة) ؛ // قم بتعيين قيمة int لعنوان الكائن المحدد إزاحة باطلة الفراغ الأصلي العام (الكائن O ، إزاحة طويلة ، int x) ؛
// إنشاء كائن ، ولكن لن يتم استدعاء مُنشئه. إذا لم تتم تهيئة الفصل ، يتم تهيئة الفصل. تخصيص الكائن الأصلي العام (الفئة <؟> CLS) يلقي instantiationException ؛
2.3 صفيف ذات صلة
/** * أبلغ عن إزاحة العنصر الأول في تخصيص التخزين لفئة صفيف معينة. إذا قام {Link #ArrayIndexScale} بإرجاع قيمة غير صفرية * لنفس الفئة ، فيمكنك استخدام عامل المقياس هذا ، مع إزاحة * الأساسية ، لتشكيل إزاحة جديدة للوصول إلى عناصر صفائف * المعطى. * * see #getint (كائن ، طويل ، int) * /// إرجاع عنوان الإزاحة للعنصر الأول في صفيف الأصلي الأصلي الأصلي int arraybaseoffset (الفئة <؟> ArrayClass) ؛ // boolean ، byte ، Short ، char ، int ، long ، float ، و double ، والكائنات لها الطرق التالية/** قيمة {chode arraybaseoff (booean) array_boolean_base_offset = theunsafe.arrayBaseOffset (Boolean []. class) ؛ /** * أبلغ عن عامل المقياس لمعالجة العناصر في التخصيص * التخصيص لفئة صفيف معينة. ومع ذلك ، فإن صفائف الأنواع "الضيقة" * لن تعمل بشكل عام مع أدوات الوصول مثل {link * #getbyte (كائن ، int)} ، وبالتالي يتم الإبلاغ عن عامل المقياس لهذه الفئات * كصفر. * * see #arraybaseoffset * see #getint (كائن ، طويل) * see #putint (كائن ، طويل ، int) * /// إرجاع الحجم الذي يشغله كل عنصر في صفيف الأصلي الأصلي الأصلي int int int intray (class <؟> ArrayClass) ؛ // Boolean ، Byte ، Short ، char ، int ، long ، تعويم ، مزدوجة ، والكائنات لها الطرق التالية/** قيمة {code arrayIndexScale (boolean []. يمكن تحديد موقع كل عنصر في الصفيف في الذاكرة من خلال ArrayBaseOffset و ArrayIndexScale.
2.4 التزامن المتعلق
2.4.1cas ذات الصلة
CAS: CompareAndswap ، إزاحة عنوان إزاحة الذاكرة ، القيمة المتوقعة المتوقعة ، القيمة الجديدة x. إذا كانت قيمة المتغير في الوقت الحالي والقيمة المتوقعة متساوية ، فحاول تحديث قيمة المتغير إلى x. إرجاع صحيح إذا كان التحديث ناجحًا ؛ خلاف ذلك ، العودة كاذبة.
// قم بتحديث القيمة المتغيرة إلى x ، إذا كانت القيمة الحالية متوقعة // o: إزاحة الكائن: إزاحة متوقعة: القيمة المتوقعة x: القيمة الجديدة ذات القيمة العامة المقارنة المنطقية الأصلية (الكائن O ، إزاحة طويلة ، الكائن المتوقع ، الكائن x) ؛ Public Final Native Boolean CompareAndswapint (Object O ، Long Offset ، int المتوقع ، int x) ؛ Public Public Native Boolean CompareAndswaplong (كائن O ، إزاحة طويلة ، متوقع طويل ، طويل X) ؛
بدءًا من Java 8 ، يتم توفير الأساليب التالية في غير آمن:
// إضافة نهائي عام int getandaddint (كائن O ، إزاحة طويلة ، int delta) {int v ؛ do {v = getIntvolatile (o ، الإزاحة) ؛ } بينما (! compareandswapint (o ، offset ، v ، v + delta)) ؛ Return V ؛} Final Final Long GetAndaddlong (Object O ، Long Exfbet ، Long Delta) {Long V ؛ do {v = getlongvolatile (o ، ارhfset) ؛ } بينما (! compareAndSwapLong (O ، Offset ، V ، V + Delta)) ؛ return v ؛} // قم بتعيين public final int getAndSetInt (object o ، long rofset ، int newValue) {int v ؛ do {v = getIntValatile (o ، ارhfset) ؛ } بينما (! compareAndSwapint (O ، Offset ، v ، newValue)) ؛ Return V ؛} Final Final Long GetAndSetLong (Object O ، Long Offset ، Long NewValue) {Long V ؛ do {v = getLongValatile (o ، offset) ؛ } بينما (! compareAndSwapLong (O ، Offset ، V ، newValue)) ؛ return v ؛} الكائن النهائي العام getAndSetObject (كائن O ، إزاحة طويلة ، كائن newValue) {Object V ؛ do {v = getObjectValatile (o ، offset) ؛ } بينما (! compareAndSwapObject (o ، offset ، v ، newValue)) ؛ العودة v ؛2.4.2 جدولة الموضوعات ذات الصلة
// إلغاء حظر الخيط العام الفراغ الأصلي UNPARK (مؤشر ترابط الكائن) ؛ // حظر مؤشر الترابط المواضيع العمومي الأصلي (ISABSOLUTE المنطقي ، وقت طويل) ؛ // الحصول على قفل كائن مراقب الفراغ الأصلي العام (كائن O) ؛ // التحرير كائن قفل Public void monitorexit (كائن O) ؛/
2.4.3 القراءة والكتابة المتقلبة
هناك الطرق التالية للأنواع الأساسية (Boolean ، Byte ، Char ، Short ، int ، Long ، تعويم ، مزدوجة) وأنواع مرجعية للكائنات في Java.
// احصل على مرجع المتغير من الإزاحة المحددة للكائن ، واستخدم دلالات التحميل من المتطايرة // تعادل النسخة المتطايرة من getObject (الكائن ، الكائن العام الطويل) getObjectvolatile (كائن O ، إزاحة طويلة) ؛ // تخزين مرجع المتغير إلى الإزاحة المحددة للكائن ، واستخدام دلالات التخزين من المتقلبة // تعادل النسخة المتطايرة من putObject (كائن ، طويل ، كائن) putObjectvolatile الأصلي (الكائن O ، إزاحة طويلة ، الكائن X) ؛
/** * إصدار {link #putObjectVolatile (كائن ، طويل ، كائن)} * الذي لا يضمن رؤية متجر على المتجر إلى * مؤشرات الترابط الأخرى. تكون هذه الطريقة مفيدة بشكل عام فقط إذا كان الحقل الأساسي * هو متطاير Java (أو إذا كانت خلية صفيف ، واحدة * يتم الوصول إليها فقط باستخدام الوصول المتطايرة). */public void putorderedObject (الكائن O ، الإزاحة الطويلة ، الكائن X) ؛ /** نسخة مرتبة/كسول من {link #putintvolatile (كائن ، طويل ، int)}*/public native void putorderedInt (كائن O ، إزاحة طويلة ، int x) ؛ /** نسخة مرتبة/كسول من {link #putlongvolatile (كائن ، طويل ، طويل)}*/public native void putorderedlong (كائن o ، إزاحة طويلة ، x) ؛2.4.4 حاجز الذاكرة ذات الصلة
تم تقديم Java 8 لتحديد حواجز الذاكرة لتجنب إعادة ترتيب الكود.
// حاجز الذاكرة ، يحظر إعادة ترتيب عمليات الحمل ، أي أن عمليات التحميل قبل إعادة ترتيب الحاجز إلى الحاجز ، لا يمكن إعادة ترتيب عمليات التحميل بعد الحاجز إلى مقدمة الحاجز المفروم الأصلي. عمليات تحميل وتخزين عمليات إعادة ترتيبها إلى مقدمة الحاجز الموصل الأصلي pullfence () ؛
2.5 الوصول المباشر للذاكرة (ذاكرة غير مركزة)
يجب أن تكون الذاكرة المخصصة بواسطة تخصيصها مجانية يدويًا (لا يتم إعادة تدويرها بواسطة GC)
// (Boolean ، Byte ، char ، Short ، int ، long ، float ، double) لها الطريقتين التاليتين: الحصول على ووضع. // احصل على قيمة int في العنوان المحدد العام int getint (العنوان الطويل) ؛ // قم بتعيين قيمة int على العنوان المحدد Public Void putint (العنوان الطويل ، int x) ؛ // الحصول على المؤشر المحلي العام getaddress (عنوان طويل) ؛ . العنوان ، البايتات ، القيمة) ؛} // تهيئة محتوى الذاكرة public public void copymemory (الكائن srcbase ، srcoffset الطويل ، الكائن destbase ، قسمة طويلة ، بايت طويلة) Bytes) ؛} // إطلاق الذاكرة العامة void void ferrememory (عنوان طويل) ؛
2.6 المرتبطة النظام
// إرجاع حجم المؤشر. قيمة الإرجاع هي 4 أو 8. /** قيمة {code addressize ()}*/public static int address_size = theunsafe.addressSize () ؛ // حجم صفحة الذاكرة. pagesize pagesize () الأصلي العام ؛3. المواد المرجعية
//www.vevb.com/article/140709.htm دعنا نتحدث عن الفصل غير الآمن في جافا
//www.vevb.com/article/140721.htm Java Magic Class: Sun.Misc.unsafe
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.