بسیاری از بخشهای کلاس Unsafe جاوا منسوخ شده و با ویژگیهای جدیدتری جایگزین میشوند که عملکرد مشابهی را ارائه میدهند. در اینجا چیزی است که شما باید بدانید.
کلاس sun.misc.Unsafe
جاوا از سال ۲۰۰۲ مورد استفاده قرار گرفته است. این کلاس روشهای سطح پایین ضروری را ارائه میکند که توسعهدهندگان چارچوب برای ارائه ویژگیها و عملکرد غیرقابل دستیابی استفاده میکنند. متأسفانه، ناامن
همچنین دارای مشکلات طولانی مدت مربوط به JVM قابلیت نگهداری. و همانطور که از نام آن پیداست، استفاده از آن کاملاً ایمن نیست. یک JEP جدیدتر پیشنهاد میکند روشهای دسترسی به حافظه sun.misc.Unsafe را حذف کند. در نسخه آتی جاوا. اما چه چیزی جایگزین آنها خواهد شد؟
این مقاله به کلاس ناامن
میپردازد، چرا برخی از روشهای آن حذف میشوند، و توسعهدهندگان برای آماده شدن برای این تغییر چه کاری میتوانند انجام دهند.
چرا متدهای ناامن جاوا در حال منسوخ شدن هستند
کلاس sun.misc.Unsafe
جاوا کارهای خاصی انجام می دهد که در غیر این صورت مجاز نیستند. قدرت های آن به دو دسته کلی تقسیم می شوند:
- دسترسی و تخصیص حافظه سطح پایین و اشاره گر
- ساخت کلاس خارج از وسایل عادی (حتی فراتر از بازتاب)
در اعمال این قدرتها، برخی از روشهای کلاس Unsafe
حفاظتهای استاندارد و مدیریت حافظه تعبیهشده در JVM را میشکنند. به همین دلیل، پیاده سازی های JVM در نحوه تطبیق ناامن
متفاوت است. در نتیجه کد شکننده تر است و ممکن است در نسخه های JVM یا سیستم عامل قابل حمل نباشد. استفاده از آن همچنین مانع از توانایی توسعه دهندگان برای توسعه داخلی JVM می شود.
رفع انواع اولیه جاوا
ناامن
تنها ویژگی قدیمی جاوا در بلوک خرد نیست – یا حداقل به دلیل تغییرات بزرگ. انواع ابتدایی مانند int
حکم “همه چیز یک شی است” را می شکنند. تعمیر آنها یکی از بسیاری از اهداف طراحی آینده نگر است که در پروژه والهالا.
چرا توسعه دهندگان از Unsafe استفاده می کنند
ناامن
همه چیز بد نیست، به همین دلیل است که برای مدت طولانی نگهداری می شود. راهنمای Sun.misc.Unsafe Baeldung شامل یک نمای کلی از کارهایی است که توسعه دهندگان می توانند با انجام دهند. کلاس ناامن
:
- نمونه سازی کلاس بدون سازنده
- دستکاری مستقیم فیلدهای کلاس
- پرتاب کردن استثناهای علامتگذاری شده زمانی که توسط محدوده کنترل نمیشوند
- دسترسی مستقیم به عملیات حافظه پشته
- دسترسی به عملیات مقایسه و تعویض (CAS)
عملیات مقایسه و تعویض جاوا خوب است مثالی از اینکه چرا ما یک کلاس ناامن
داریم. CAS یک دستورالعمل در سطح سخت افزار است که امکان دسترسی به حافظه اتمی را فراهم می کند. Atomicity مزایای عملکرد قابل توجهی را به رشته های همزمان می دهد زیرا به ما امکان می دهد حافظه را بدون مسدود کردن تغییر دهیم. به طور سنتی، APIهای استاندارد جاوا نمیتوانستند از این ویژگی استفاده کنند، زیرا این ویژگی مختص سیستم عامل است.
در اینجا یک قطعه از عملیات مقایسه و تعویض با استفاده از ناامن
، از معرفی Oracle به sun.misc.Unsafe:
public final class AtomicCounter implements Counter {
private static final Unsafe unsafe;
private static final long valueOffset;
private volatile int value = 0;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe"); // (1)
f.setAccessible(true); // (2)
unsafe = (Unsafe) f.get(null); // (3)
valueOffset = unsafe.objectFieldOffset
(AtomicCounter.class.getDeclaredField("value")); // (4)
} catch (Exception ex) { throw new Error(ex); }
}
@Override
public int increment() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1; // (5)
}
@Override
public int get() {
return value;
}
}
متوجه خواهید شد که دسترسی به ناامن
نیز عجیب است. این یک عضو کلاس ایستا است که ابتدا باید با بازتاب (۱) به آن دسترسی پیدا کرد، سپس به صورت دستی روی دسترس
(۲) تنظیم کرد و سپس با بازتاب (۳) به آن ارجاع داد.
با در دست داشتن کلاس Unsafe
، افست فیلد مقدار را در کلاس AtomicCounter
فعلی (۴) دریافت می کنیم. افست به ما می گوید که فیلد در کجای حافظه در رابطه با تخصیص حافظه کلاس قرار دارد. توجه داشته باشید که در اینجا ما با اشاره گرهایی سروکار داریم که ممکن است برای توسعه دهندگان جاوا ناآشنا باشد، اگرچه آنها در زبان های مدیریت حافظه مستقیم مانند C/C++ استاندارد هستند. اشاره گرها با قرار دادن مسئولیت دسترسی به حافظه بر عهده برنامهنویس – چیزی مکانیسم جمعآوری زباله جاوا به صراحت برای جلوگیری از آن طراحی شده است.
برای اجرای دستور CAS، تابع getAndAddInt()
(۵) فراخوانی می شود. این به سیستم عامل میگوید دستورات اتمی را با استفاده از this
بهعنوان چارچوب مرجع، در مکان valueOffset
و با “دلتا” ۱-به معنی عملیات اجرا کند. سیستم باید ۱ افزایش یابد.
بازسازی sun.misc.Unsafe
اکنون طعم استفاده از ناامن
را چشیده اید. این مثال همچنین برخی از اشکالات آن را برجسته می کند.
انجام عملیات حافظه نادرست می تواند باعث “خراش سخت” JVM بدون ایجاد استثنا در پلت فرم شود. مدیریت ضعیف حافظه همچنین میتواند منجر به نشت حافظه شود. در برخی از زبان ها ایجاد آن بسیار آسان و تشخیص و رفع آن دشوار است. دسترسی مستقیم به حافظه همچنین میتواند حفرههای امنیتی مانند سرریزهای بافر را باز کند. (برای بررسی بیشتر در مورد معایب استفاده از sun.misc.Unsafe، به Stack Overflow مراجعه کنید.)
اما اشکالات ایجاد شده توسط برنامه نویس تنها بخشی از مشکل است. استفاده از ناامن
همچنین منجر به کدهای خاص پیاده سازی می شود. این بدان معناست که برنامه هایی که از آنها استفاده می کنند ممکن است قابل حمل نباشند. همچنین تغییر پیاده سازی های خود در آن مناطق را برای JVM دشوارتر می کند.
به همه این دلایل، توسعه دهندگان جاوا در حال حرکت به سمت معرفی روشی هستند که توسط پلتفرم تعیین شده برای انجام اقداماتی که در حال حاضر با کلاس ناامن
مرتبط هستند. مشکل این است که کد با استفاده از sun.misc.Unsafe
در همه جا وجود دارد. در نقاط بحرانی به فریمورک های مختلف برخورد می کند. و از آنجایی که ناامن
با عملیات سطح پایین لمسی سروکار دارد، کد بهویژه برای بازگردانی مشکل است.
گزینه های جایگزین sun.misc.Unsafe
توسعه دهندگان جاوا در حال حاضر در حال جایگزینی ویژگی های ناامن
با نسخه های استاندارد و کمتر مشکل ساز هستند. بیایید به گزینه های جایگزین نگاه کنیم، که برخی از آنها در جاوا ۹ معرفی شده اند.< /p>
VarHandles
دستههای متغیر در JEP 193 توضیح داده شده است. این ویژگی یکی از بزرگترین کاربردهای ناامن
را پوشش میدهد، که دسترسی مستقیم و دستکاری فیلدهای روی پشته است. خواندن اهداف JEP برای درک اینکه این ویژگی چه می کند ارزش دارد، اما در اینجا خلاصه ای وجود دارد:
- نباید JVM را در وضعیت حافظه خراب قرار داد.
- دسترسی به فیلد یک شیء از قوانین دسترسی مشابه با کدهای بایت
getfield
وputfield
پیروی میکند، علاوه بر محدودیتی که یکfinal
فیلد یک شی را نمی توان به روز کرد. - ویژگیهای عملکرد آن باید مشابه یا مشابه عملیاتهای
sun.misc.Unsafe
باشد. - API باید بهتر از
sun.misc.Unsafe
API باشد.
به طور کلی، VarHandles نسخه ایمنتر و بهتر از ویژگیهای Unsafe
را در اختیار ما قرار میدهد و عملکرد را به خطر نمیاندازد. با مراجعه به Javadoc for AccessModes. متوجه خواهید شد که مقایسه و تبادل همراه با بسیاری از انواع عملیات ابتدایی دیگر پشتیبانی می شود.
استفاده از نمونههای VarHandle
روشی پاک و ایمن برای انجام بسیاری از عملیات سطح پایین مستقیماً در فیلدها است، بدون اینکه خطراتی را که با ناامن
انجام میدهیم، انجام دهیم.
MethodHandles
کلاس MethodHandles
(JEP 274) دارای یک Lookup که جایگزین استفاده از بازتاب برای به دست آوردن و تغییر مجوزها در فیلدها (تکنیکی که قبلاً در مثال CAS دیدید). با این کلاس، مجوزها به جای اینکه مستقیماً با بازتاب تنظیم شوند، بر اساس دسترسی به کد حاوی اعطا می شوند.
API Stack-Walking
Unsafe.getCallerClass()
تا حدی با Stack-Walking API ارائه شده در JEP 259. این یک راه ایمن تر، هرچند دورگرد بیشتر برای دسترسی به کلاس تماس گیرنده فراهم می کند.
راه حل هنوز مورد نیاز است
برخی از ویژگیهای برجسته ناامن
باید جایگزین شوند. یک مثال مهم ظرفیت ایجاد پروکسی و مسخره است. (بن ایوانز در مقاله مجله جاوا خود، ناامن با هر سرعتی.)
همچنین جالب است که ببینید پروژه های دنیای واقعی چگونه با این مشکل دست و پنجه نرم می کنند. برای مثال، نحوه برخورد پروژه Objenesis Git را در نظر بگیرید. href=”https://github.com/easymock/objenesis/issues/61″ rel=”nofollow”>Unsafe.defineClass() در حال حذف از API.
بر اساس این مثال، میتوانیم ببینیم که هنوز کارهایی برای جایگزینی کامل قابلیتهای Unsafe
در ایجاد کلاسهای بدون سازنده وجود دارد.
نتیجه گیری
حلقه برنجی برای سفر ناامن
جاوا این است که به طور کامل همه ویژگیهای دسترسی به حافظه ناامن
را با نسخههای مجاز جایگزین کند. همانطور که می بینید، این کار همه در یک مکان اتفاق نمی افتد. قطعات و قطعات از طریق APIهای جدیدتر اضافه خواهند شد، اگرچه VarHandle
به بخش بزرگی از کار می پردازد.
داشتن نسخههای جدید عملکرد تنها نیمی از کار است. چارچوبها و پروژههای مختلفی که در حال حاضر به روشهای ناامن
متکی هستند باید به گزینههای جدید مهاجرت کنند، که به هیچ وجه ساده نیست. در برخی موارد، به بازسازی جدی نیاز دارد.
به تدریج، JVM احتمالاً به منسوخ شدن و حذف ویژگیهای ناامن
ادامه میدهد، زیرا جایگزینهای معتبر تقویت میشوند. به نظر می رسد که مباشران جاوا متعهد هستند که با مسئولیت پذیری این ناحیه قدیمی از پلتفرم را اصلاح کنند و در عین حال از پایداری اکوسیستم وابسته به آن اطمینان حاصل کنند.
پست های مرتبط
چه اشکالی دارد Java’s sun.misc.Unsafe؟
چه اشکالی دارد Java’s sun.misc.Unsafe؟
چه اشکالی دارد Java’s sun.misc.Unsafe؟