39 ميزات جديدة لتكون متاحة في جافا 12

من مقابلة رائعة مع هابري: "سيمون ريتر هو شخص عمل على جافا منذ البداية ويستمر في القيام بذلك كنائب المدير التقني لأزول ، وهي شركة تعمل على آلة Zing JVM الافتراضية وأحد أفضل جامعي القمامة ، C4 (Continuously Concurrent Compacting جامع) »
فيما يلي ترجمة لمقالته حول ميزات JDK 12 الجديدة وبعض الصعوبات التي قد تواجهها عند الترحيل إلى بنية جديدة.

كتبت العديد من منشورات المدونة التي تسرد جميع التغييرات لكل من أحدث إصدارات Java ( JDK 10 ، JDK 11 ). سأستكشف الآن الجانب المظلم من JDK 12 ، مع التركيز على بعض المزالق التي يمكن أن تسبب مشاكل إذا كنت ترغب في نقل التطبيق إلى هذا الإصدار.



يحتوي JDK 12 على أقل عدد من الميزات الجديدة من جميع إصدارات Java حتى الآن (لقد عدت 109 في JDK 10 و 90 في JDK 11). هذا ليس سيئًا - نظرًا لوجود دورات إطلاق ، ستتضمن بعض الإصدارات مزيدًا من التغييرات وبعضها أقل.


سوف أقسم الوظائف الجديدة إلى مناطق منطقية واضحة: Java والمكتبات و JVM ووظائف JDK الأخرى.


تغييرات اللغة


إن الوظيفة التي أراها I (وافترض أن العديد من الأشخاص الآخرين) ستراعي الأكثر وضوحًا في JDK 12 هي بيان التبديل الجديد ( JEP 325 ). هذا هو أيضًا تغيير اللغة الأول الذي يتم استخدامه كدالة "للمعاينة". تم تقديم فكرة "المعاينة" في أوائل عام 2018 كجزء من JEP 12 . هذه في الأساس طريقة لتمكين إصدارات بيتا من الميزات الجديدة باستخدام خيارات سطر الأوامر. باستخدام المعاينة ، لا يزال من الممكن إجراء تغييرات بناءً على ملاحظات المستخدم ، وفي أسوأ الحالات ، قم بإزالة الوظيفة بالكامل إذا لم يتم استلامها بشكل صحيح. مفتاح معاينة الوظائف هو أنها غير مضمنة في مواصفات Java SE. حول التبديل الجديد هناك ترجمة جيدة للغاية على حبري.
في JDK 12 ، أصبح المحول تعبيرًا يقيم "محتواه" لإنتاج نتيجة. سأوضح على الفور أن هذا لا يؤثر على التوافق مع الإصدارات السابقة ، لذلك لن تحتاج إلى تغيير أي رمز يستخدم التبديل كمشغل.


سأستخدم المثال من JEP ، لأنه بسيط وواضح:


التبديل القديم
int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; default: throw new IllegalStateException("Huh? " + day); } 

كما ترون ، نقوم بتعيين يوم من أيام الأسبوع على اسم day المتغير ، ثم numLetters بتعيين قيمة numLetters . الآن بعد أن أصبح رمز التبديل عاملًا ، يمكننا أن نقوم بتعيين مرة واحدة (مما يقلل بشكل كبير من احتمال وجود رمز خطأ) باستخدام نتيجة بيان التبديل:


 int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; default -> throw new IllegalStateException("Huh? " + day); }; 

ستلاحظ بسرعة تغييرين في بناء الجملة. عثر مطورو OpenJDK على وظيفة بناء جملة غير معروفة تسمى قائمة مفصولة بفواصل. أيضا عامل التعبير lambda -> يجعل إرجاع القيمة أسهل. لا يزال بإمكانك استخدام break بقيمة إذا كنت تريد ذلك حقًا. هناك العديد من التفاصيل الأخرى حول هذه الميزة ، ولكن من المحتمل أن يكون من السهل قراءة JEP.


المكتبات


هناك تغيير واحد أجده مفيدًا للغاية. هناك أيضا عدد من الثانوية.


جامع teeing


يحتوي Stream API ، كالمعتاد ، على أداة تجميع جديدة ، يتم توفيرها بواسطة فئة الأداة المساعدة Collectors. يمكن الحصول على أداة تجميع جديدة باستخدام طريقة teeing() . يأخذ جامع teeing ثلاث حجج: جامعان و bifunction. لفهم عمل هذا المجمع ، أوصي بهذا المقال عن حبري .
لفهم كيف يفعل هذا ، قمت برسم مخطط:


صورة

يتم تمرير جميع القيم من دفق الإدخال إلى كل جامع. يتم تمرير نتيجة كل جامع كوسيطات إلى BiFunction وتوليد النتيجة النهائية.


مثال بسيط هو حساب متوسط ​​القيمة (نعم ، أعلم أن هناك بالفعل جامعي لهذا ، مثل averagingInt() ، ولكن هذا مثال بسيط للمساعدة في فهم المفهوم).


 /* Assume Collectors is statically imported */ double average = Stream.of(1, 4, 2, 7, 4, 6, 5) .collect(teeing( summingDouble(i -> i), counting(), (sum, n) -> sum / n) ); 

يقوم المجمع الأول بحساب مجموع دفق الإدخال ، والثاني - عدد العناصر. تقسم BiFunction المجموع على عدد العناصر للحصول على القيمة المتوسطة.


java.io


InputStream skipNBytes(long n) - يتخطى ويتجاهل بالضبط بايت n من دفق الإدخال InputStream. إذا كان n هو صفر أو أقل ، فلن يتم تخطي وحدات البايت.


java.lang


ظهرت حزمة جديدة ، java.lang.constant ، والتي تعد جزءًا من واجهة برمجة تطبيقات JVM الثابتة ، JEP 334 .


يحتوي كل ملف فئة Java على تجمع ثابت يخزّن المعاملات للحصول على تعليمات bytecode في الفصل الدراسي. يصعب على المطورين معالجة ملفات الفصل بسبب مشاكل في تحميل الفئات. توفر واجهة برمجة تطبيقات JVM الثابتة أنواع مرجعية رمزية لوصف كل شكل من أشكال ثابت (فئة ، ثابت قابل للتحميل ، MethodHandle ، MethodHandle ثابت ، MethodType ثابت).


كما أثرت في العديد من الطبقات الأخرى. تحتوي جميع الفئات التالية الآن على describeConstable() طريقة:


  • فئة
  • مزدوج
  • التعداد
  • عوامة
  • عدد صحيح
  • طويل
  • سلسلة
  • MethodHandle
  • MethodType
  • VarHandle

كوني بريطاني ، أجد أنه أمر مضحك للغاية. مصطلح كونستابل ، describeConstable كونستابل يستخدم منذ القرن الحادي عشر ، وهذه هي الطريقة التي نشير فيها إلى ضباط الشرطة. وهو أيضًا اسم الفنان الشهير في القرن الثامن عشر ، جون كونستابل. هذا يجعلني أتساءل عما إذا كانت طريقة describeTurner() ستكون في إصدار مستقبلي. من الواضح ، أنه في هذه الحالة هو اختصار للطاولة Constant Table ، لا يتعلق بموظف قانوني أو رسام المناظر الطبيعية.


تتضمن الفئات التالية الآن أسلوب resolveConstantDesc() :


  • مزدوج
  • Enum.EnumDesc
  • عوامة
  • عدد صحيح
  • طويل
  • سلسلة

java.lang.Character


تم تحديث الطبقات الداخلية لتشمل كتل يونيكود جديدة. أرغب دائمًا في رؤية ما وجده الأشخاص لإضافته إلى Unicode ، فيما يلي بعض الأمثلة:


  • رموز الشطرنج
  • أرقام المايا
  • اللغة السغدية هي لغة إيرانية شرقية لم تعد تستخدم في القرن الحادي عشر.
  • Sogdian القديم هو إصدار أقدم (وأظن أنه أكثر محدودية) من Sogdian

java.lang.Class


arrayType() بإرجاع Class لنوع الصفيف الذي تم وصف نوع المكون الخاص به بواسطة هذه Class . يمكن التحقق من ذلك باستخدام jshell :


 jshell> (new String[2]).getClass().getName() $11 ==> "[Ljava.lang.String;" jshell> (new String[2]).getClass().arrayType() $12 ==> class [[Ljava.lang.String; jshell> "foo".getClass().arrayType() $15 ==> class [Ljava.lang.String; 

لست متأكدًا تمامًا من معنى هذه الطريقة ، حيث أن كل ما تفعله هو إضافة Class إلى النوع الذي تمثله هذه الفئة.


componentType() ، مثل getComponentType() . يطرح السؤال - لماذا تضيف طريقة زائدة عن الحاجة؟


descriptorString() - مرة أخرى ، تُرجع نفس النتيجة كـ getName() . ومع ذلك ، من الضروري أن تقوم Class الآن بتنفيذ واجهة TypeDescriptor المرتبطة بواجهة برمجة تطبيقات JVM الثابتة الجديدة.


lava.lang.String


indent() - يضيف سلسلة من المسافات indent() إلى سلسلة. إذا كانت المعلمة سالبة ، فسيتم إزالة هذا العدد من المسافات البادئة (إن أمكن).


transform() - يطبق الوظيفة المتوفرة على سلسلة. قد لا تكون النتيجة سلسلة.


java.lang.invoke


VarHandle الآن toString() لإرجاع وصف مضغوط.


java.net.SecureCacheResponse و java.net.ssl.HttpsConnection لديهم طريقة جديدة ، getSSLSession() والتي ترجع Optional يحتوي على SSLSession المستخدمة في الاتصال.


java.nio.files


تحتوي فئة Files على طريقة جديدة ، mismatch() ، والتي تقوم بإيجاد وإرجاع موضع بايت عدم التطابق الأول في محتويات ملفين ، أو -1L إذا لم يكن هناك عدم تطابق.


java.text


هناك فئة جديدة CompactNumberFormat . هذا هو فئة فرعية من NumberFormat رقم عشري في نموذج مضغوط. مثال على نموذج مضغوط - 1M بدلاً من 1000000 ، وبالتالي - يتطلب حرفين بدلاً من تسعة أحرف. تم توسيع NumberFormat و getCompactNumberInstance() طريقة getCompactNumberInstance() الجديدة. يوجد أيضًا تعداد جديد ، NumberFormatStyle والذي له معنيان: LONG و SHORT.


java.util.concurrent


يتضمن CompleteStage الآن العديد من النماذج المحملة بثلاث طرق:


  • exceptionallyAsync
  • exceptionallyCompose
  • exceptionallyComposeAsync

تعمل هذه الطرق على توسيع إمكانيات إنشاء " CompletionStage جديد من "موجود" ، " CompletionStage إذا انتهى الحال مع استثناء. تحقق من وثائق API للحصول على التفاصيل.


javax.crypto


تحتوي فئة Cipher على طريقة toString() جديدة تقوم بإرجاع سلسلة تحتوي على تحويل Cipher والوضع والموفر.


javax.naming.ldap.spi


هذه حزمة جديدة في JDK 12 وهي تحتوي على فئتين: LdapDnsProvider ، وهي فئة الموفرين لعمليات البحث عن DNS أثناء عمليات LDAP ، و LdapDnsProviderResults التي تغلف نتيجة بحث DNS لعنوان URL LDAP.


أرجوحة


لا يزال يجري تحديث سوينغ! نعم ، getChooserShortcutPanelFiles() لديه الآن طريقة getChooserShortcutPanelFiles() جديدة. تقوم بإرجاع مجموعة من الملفات التي تمثل القيم المراد عرضها افتراضيًا في شريط اختصار تحديد الملف.


التغييرات JVM


JEP 189: شيناندواه : جامع البيانات المهملة في وقت منخفض


شيناندواه هو مشروع بحثي أعلنته ريد هات في عام 2014 ويركز على متطلبات تطبيق الكمون المنخفض لإدارة الذاكرة في JVM. أهدافها هي وقت توقف مؤقت أقصى يبلغ 1..10 مللي ثانية كومة الذاكرة المؤقتة لأكثر من 20 جيجابايت ( وبالتالي فهو غير مخصص للتطبيقات الصغيرة - كما أجاب أحد مطوري Shenandoah ، هذا ليس كذلك ويقوم بعمل ممتاز مع التطبيقات الصغيرة). تم تصميم أداة التجميع هذه لتعمل بالتوازي مع مؤشرات ترابط التطبيق ، لذا تجنب المشكلات التي نراها في معظم أدوات تجميع البيانات المهملة.


JEP 344: مجموعات G1 المختلطة


يهدف هذا التغيير إلى تحسين سلوك جامع G1 عندما يصل إلى هدف التأخير المحدد. يقسم G1 مساحة الكومة (القديمة والقديمة) إلى مناطق. والفكرة هي أنه في الجيل القديم لا تحتاج إلى جمع القمامة في عملية واحدة. عندما تحتاج G1 إلى جمع البيانات المهملة ، فإنها تحدد المناطق التي تحددها. وهذا ما يسمى مجموعة جمع. قبل إصدار JDK 12 ، عندما بدأ العمل في المجموعة ، كان لابد من إكمال كل العمل ، في جوهره ، كعملية ذرية. كانت المشكلة أنه في بعض الأحيان بسبب التغييرات في استخدام التطبيق لمساحة الكومة ، اتضح أن مجموعة المجموعة كانت كبيرة للغاية واستغرقت وقتًا طويلاً في التجميع ، مما أدى إلى حقيقة أنه لم يتم الوصول إلى وقت الإيقاف المؤقت.


في JDK 12 ، إذا حددت G1 هذا الموقف ، فسوف يقطع جمع البيانات في منتصف الطريق إذا لم يؤثر ذلك على قدرة التطبيق على مواصلة تخصيص مساحة للكائنات الجديدة. سيكون التأثير الصافي لـ G1 أفضل عند الوصول إلى وقت توقف مؤقت قصير.


JEP 346: إرجاع بسرعة الذاكرة المخصصة غير المستخدمة من G1


هذا تحسين آخر للأداء في G1 ، لكن هناك تحسينًا آخر يتعلق بكيفية تفاعل JVM مع بقية النظام. من الواضح أن الذاكرة مطلوبة لكومة الذاكرة المؤقتة لـ JVM ، وعند بدء التشغيل ، تطلب الذاكرة من مُخصص الذاكرة الظاهرية لنظام التشغيل. عند بدء تشغيل التطبيق ، قد تكون هناك أوقات ينخفض ​​فيها مقدار الذاكرة المطلوبة للكومة ، ويمكن إرجاع جزء من الذاكرة المخصصة إلى نظام التشغيل لاستخدامها من قبل التطبيقات الأخرى.


يقوم G1 بهذا بالفعل ، ولكن لا يمكنه القيام بذلك إلا في أحد المكانين. أولا ، خلال مجموعة كاملة ، وثانيا ، خلال واحدة من الدورات الموازية. يحاول G1 عدم القيام بمجموعة كاملة ، ومع انخفاض استخدام الذاكرة ، قد تكون هناك فترات مهمة بين دورات المجموعة. هذا يؤدي إلى حقيقة أن G1 يمكنه الاحتفاظ بذاكرة ثابتة لفترة طويلة.


في JDK 12 ، ستحاول G1 بشكل دوري متابعة أو تشغيل حلقة متوازية بينما يكون التطبيق في وضع الخمول لتحديد الاستخدام الكلي لكومة Java. يمكن إرجاع الذاكرة غير المستخدمة إلى نظام التشغيل في الوقت المناسب وبطريقة يمكن التنبؤ بها.


علامة سطر الأوامر الجديدة -XX:G1PeriodicGCInterval يمكن استخدامها لتعيين عدد المللي ثانية بين الشيكات.


ستؤدي هذه الميزة إلى استخدام أكثر تحفظًا لذاكرة JVM للتطبيقات التي ظلت خاملاً لفترات طويلة من الوقت.


ميزات JDK جديدة أخرى


JEP 230: مجموعة العلامات الصغيرة


تم تطوير Java Microbenchmarking Harness (JMH) بواسطة Alexey Shipilev عندما كان يعمل في Oracle ويوفر منصة شاملة لتطوير اختبارات الأداء لتطبيقات Java. قام Alexey بعمل رائع لمساعدة الناس على تجنب العديد من الأخطاء البسيطة التي يرتكبونها عند محاولة تحليل أداء التطبيق: الاحماء ، تجنب الاستثناءات ، إلخ.


يمكن الآن تضمين JMH في OpenJDK. يمكن لأي شخص مهتم بالعمل على JDK نفسه وتغيير الرمز استخدام هذا لمقارنة الأداء قبل وبعد التغييرات ، وكذلك لمقارنة الأداء في الإصدارات المختلفة. يتم تضمين عدد من الاختبارات لتمكين الاختبار ؛ تصميم JMH هو أنه من السهل إضافة اختبارات جديدة إلى حيث هناك حاجة إليها.


JEP 340: منفذ Aarch64 واحد ، وليس اثنين


يحتوي OpenJDK على منفذين لهندسة Arm64 ، أحدهما يوفره Oracle والآخر بواسطة Red Hat. نظرًا لأن هذا لم يكن ضروريًا ، وتوقف Oracle عن دعم Arm لثنائيات JDK الخاصة به ، فقد تقرر استخدام منفذ Red Hat فقط ، الذي لا يزال مدعومًا ومطورًا.


341 JEP: أرشيف CDS الافتراضي


تستخدم فئة مشاركة البيانات (CDS) لتكون ميزة تجارية في Oracle JDK. مع انتقال حديث تم إجراؤه في JDK 11 لإزالة جميع الاختلافات الوظيفية بين Oracle JDK و OpenJDK ، تم تضمينه في OpenJDK.


لاستخدام CDS ، تحتاج إلى أرشيف تم إنشاؤه للفئات التي يتم تحميلها عند بدء تشغيل التطبيق. يحتوي JDK 12 للأنظمة الأساسية 64 بت الآن على ملف classes.jsa في دليل lib/server . هذا هو أرشيف CDS لـ "الفئات الافتراضية". أفترض أن هذا يعني جميع الفئات العامة في وحدات JDK ؛ لم أتمكن من إيجاد طريقة لفك ضغطها للتحقق. منذ تمكين CDS افتراضيًا ، وهو ما يعادل الخيار -Xshare:auto في سطر الأوامر ، سيستفيد المستخدمون من أوقات بدء تشغيل التطبيق المحسنة منه.


النتائج


يوفر JDK 12 عددًا صغيرًا من الوظائف وواجهات برمجة التطبيقات ، مع switch الأكثر إثارة للاهتمام للمطورين. بالتأكيد سيقدر مستخدمو G1 تحسينات الأداء.


مع الإصدار الجديد من الإصدار ، أنصح جميع المستخدمين باختبار تطبيقاتهم في هذا الإصدار. سيساعدك تتبع التغييرات الإضافية في تجنب المفاجآت إذا قررت الانتقال إلى الإصدار التالي من الدعم طويل الأجل.


لدينا إصدارات JDK 12 مجانية لـ Zulu Community Edition لمساعدتك في الاختبار. تأكد من تجربتها.

Source: https://habr.com/ru/post/ar446590/


All Articles