JavaRush /مدونة جافا /Random-AR /من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا. الجزء 2

من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا. الجزء 2

نشرت في المجموعة
هذه المقالة هي الجزء الثاني من مراجعتي للابتكارات في إصدارات Java 8-13. الجزء الأول هنا . دون مزيد من اللغط، دعنا ننتقل: إلى 25 سبتمبر 2018، عندما تم إصدار JDK الجديد:

جافا 11

من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 2 - 1

فار (في لامدا)

من الآن فصاعدًا، يمكننا تحديد أنواع معلمات لامدا أو حذفها عند كتابة تعبير لامدا (تعبيرات لامدا المكتوبة ضمنيًا):
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
يمكنك أيضًا إضافة تعليقات توضيحية إلى معلمات lambda دون الحاجة إلى كتابة اسم نوع المتغير بالكامل:
Function<String, String> append = (@NonNull var string) -> string + " Text";

ض (زك)

ZGC هو أداة تجميع البيانات المهملة الجديدة التي لا تعمل. فهو يخصص ذاكرة جديدة ولكن لا يعيد تشغيلها أبدًا. تعد ZGC بإدارة كميات كبيرة من الذاكرة ذات إنتاجية عالية وزمن وصول منخفض (ZGC متاحة فقط على الأنظمة الأساسية 64 بت). التلوين المرجعي - تستخدم ZGC مؤشرات 64 بت بتقنية تسمى تلوين المؤشر. تقوم المؤشرات الملونة بتخزين معلومات إضافية حول الكائنات الموجودة في الكومة. عندما تصبح الذاكرة مجزأة، يساعد ذلك على تجنب تدهور الأداء عندما يحتاج GC إلى إيجاد مساحة لتخصيص جديد. تتكون عملية جمع البيانات المهملة باستخدام ZGC من الخطوات التالية:
  1. توقفات العالم: نبحث عن نقاط البداية للوصول إلى الكائنات الموجودة في الكومة (مثل المتغيرات المحلية أو الحقول الثابتة)؛
  2. تقاطع الرسوم البيانية الكائنية بدءًا من الروابط الجذرية. نقوم بوضع علامة على كل كائن نصل إليه (يمشي ZGC عبر الرسم البياني للكائن ويفحص العلامات الملونة، ويضع علامة على الكائنات المتاحة)؛
  3. التعامل مع بعض حالات الحافة، مثل الروابط الضعيفة؛
  4. تحريك الكائنات الحية، وتحرير مساحات كبيرة من الكومة لتسريع عملية التخصيص.
  5. عندما تبدأ مرحلة النقل، تقوم ZGC بتقسيم الكومة إلى صفحات وتشغيل صفحة واحدة في كل مرة؛
  6. تقوم ZGC بإنهاء حركة أي جذور وتحدث بقية الحركة.
هذا الموضوع معقد للغاية ومربك. تتطلب المناقشة التفصيلية مقالة منفصلة، ​​لذلك سأتركها هنا:

إبسيلون جي سي

Epsilon عبارة عن أداة تجميع البيانات المهملة التي تتعامل مع تخصيص الذاكرة ولكنها لا تنفذ أي آلية حقيقية لاستعادة الذاكرة. بمجرد استنفاد كومة Java المتوفرة، سيتم إيقاف تشغيل JVM. أي، إذا بدأت في إنشاء كائن في مصفوفة لا نهائية دون الارتباط بمرجع باستخدام أداة تجميع البيانات المهملة هذه، فسوف يتعطل التطبيق بسبب OutOfMemoryError (وإذا كان مع أي شيء آخر، فلن يحدث ذلك، لأنه سيقوم بتنظيف الكائنات بدون مراجع) . لماذا هو مطلوب؟ إليكم السبب:
  1. اختبار أداء.
  2. اختبار ضغط الذاكرة.
  3. اختبار واجهة VM.
  4. عمل قصير للغاية.
  5. تحسينات زمن الوصول لآخر قطرة.
  6. تحسينات الإنتاجية الأخيرة.
روابط مفيدة: ابتكارات أخرى:
  1. ByteArrayOutputStreamحصلت على طريقة void writeBytes(byte [])تكتب كل البايتات من الوسيطة إلى OutputStream.
  2. FileReaderوحصلت FileWriterعلى مُنشئات جديدة تسمح لك بتحديد Charset.
  3. Pathأمسك طريقتين جديدتين، of(String, String [])وإرجاع Pathمسار أو تسلسل من السلاسل من وسيطة سلسلة والتي عند دمجها تشكل سلسلة مسار و of(URI): إرجاع المسار من URI.
  4. Pattern- تلقى طريقة asMatchPredicate()تتحقق مما إذا كانت سلسلة إدخال معينة تتطابق مع نمط معين (سواء كانت تسمح لك بإنشاء مسند باستخدام تعبير عادي بحيث يمكنك، على سبيل المثال، تصفية البيانات في الدفق).
  5. Stringلقد التقطت العديد من الطرق المفيدة، مثل:
    • String strip(): سيعيد لنا سلسلة هي هذه السلسلة، مع إزالة كافة المسافات في بداية ونهاية السلسلة (على غرار Trim()، ولكن يحدد المسافات بشكل مختلف)؛
    • String stripLeading(): سيعيد لنا السلسلة التي هي هذه السلسلة، مع إزالة أي مسافات بادئة من السلسلة؛
    • String stripTrailing(): سيعيد لنا السلسلة التي هي هذه السلسلة، مع إزالة أي مسافات في نهاية السلسلة؛
    • Stream lines(): سيعود إلينا Streamمن Stringهذه السلسلة، مفصولاً بفواصل الأسطر؛
    • String repeat(int): سيعيد لنا سلسلة عبارة عن سلسلة من هذه السلسلة، مكررة عدة مرات.
    • boolean isBlank(): سيعود صحيحًا إذا كانت السلسلة فارغة أو تحتوي على مسافات فقط، وإلا فسيكون خطأ.
  6. Thread- تمت إزالة طرق التدمير () والإيقاف (القابل للرمي).
  7. Filesحصلت على عدد من الأساليب الجديدة:
    • String readString(Path): يقرأ جميع البيانات من ملف إلى سلسلة، أثناء فك التشفير من البايتات إلى الأحرف باستخدام ترميز UTF-8؛
    • String readString(Path, Charset): كما هو الحال في الطريقة المذكورة أعلاه، مع اختلاف أن فك التشفير من البايتات إلى الأحرف يتم باستخدام مجموعة الأحرف المحددة؛
    • Path writeString (Path, CharSequence, OpenOption []): يكتب سلسلة من الأحرف إلى ملف. يتم ترميز الأحرف إلى بايت باستخدام ترميز UTF-8؛
    • Path writeString(Path, CharSequence,Charset, OpenOption []): بنفس الطريقة المذكورة أعلاه، يتم تشفير الأحرف فقط في وحدات البايت باستخدام التشفير المحدد في مجموعة الأحرف.
كانت هذه هي ابتكارات واجهة برمجة التطبيقات الأكثر إثارة للاهتمام (في رأيي المتواضع)، إليك بعض المواد لمراجعة أكثر تفصيلاً:

جافا 12

مرت ستة أشهر ونرى المرحلة التالية في تطور جافا. لذا، حان الوقت لإخراج مجرفة المعرفة والحفر. من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 2 - 2

تحديث G1

تم إجراء التحسينات التالية لـ G1:
  1. استعادة الذاكرة المخصصة غير المستخدمة

    يوجد في ذاكرة Java الكومة ما يسمى بالذاكرة غير المستخدمة (أو بمعنى آخر، غير نشطة). في Java 12 قرروا حل هذه المشكلة الآن:

    • يقوم G1 بإرجاع الذاكرة من الكومة في GC كامل أو أثناء حلقة متوازية؛ يحاول G1 منع GC الكامل ويبدأ حلقة متوازية بناءً على تخصيص الكومة. سيتعين علينا إجبار G1 على إرجاع الذاكرة من الكومة.

    يركز هذا التحسين على الأداء من خلال إعادة الذاكرة تلقائيًا من الكومة إلى نظام التشغيل عندما لا يكون G1 قيد الاستخدام.

  2. إحباط المجموعات المختلطة عند تجاوز وقت الإيقاف المؤقت

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

المعيار الدقيق

قدمت Java 12 اختبارات قياس الأداء الدقيقة بحيث يمكن اختبار أداء JVM بسهولة باستخدام المعايير الحالية. سيكون هذا مفيدًا جدًا لأي شخص يريد العمل على JVM نفسه. يتم إنشاء الاختبارات المضافة باستخدام Java Microbenchmark Harness (JMH). تسمح هذه الاختبارات باختبار الأداء المستمر على JVM. يقترح JEP 230 تقديم ما يقرب من 100 اختبار، مع تقديم اختبارات جديدة مع إصدار إصدارات جديدة من Java. فيما يلي مثال على الاختبارات التي تتم إضافتها .

شيناندواه

هذه خوارزمية لجمع البيانات المهملة (GC) تهدف إلى ضمان أوقات استجابة منخفضة (الحد الأدنى هو 10-500 مللي ثانية). يؤدي هذا إلى تقليل وقت إيقاف GC مؤقتًا عند القيام بأعمال التنظيف بالتزامن مع تشغيل سلاسل عمليات Java. في Shenandoah، يكون وقت الإيقاف المؤقت مستقلاً عن حجم الكومة. هذا يعني أن وقت الإيقاف المؤقت سيكون هو نفسه بغض النظر عن حجم الكومة لديك. هذه ميزة تجريبية ولم يتم تضمينها في الإصدار القياسي (Oracle) لـ OpenJDK.

تحسين التبديل

قام Java 12 بتحسين تعبيرات التبديل لمطابقة الأنماط. تم تقديم بناء جملة جديد L →. فيما يلي قائمة بالنقاط الرئيسية للمفتاح الجديد :
  1. يلغي بناء الجملة الجديد الحاجة إلى بيان فاصل لمنع الأخطاء.
  2. لم تعد تعبيرات التبديل تفشل.
  3. بالإضافة إلى ذلك، يمكننا تحديد ثوابت متعددة في تسمية واحدة.
  4. الحالة الافتراضية مطلوبة الآن في تعبيرات التبديل.
  5. يتم استخدام الفاصل في تعبيرات التبديل لإرجاع القيم من السجل نفسه (في الواقع، يمكن للمحول إرجاع القيم).
دعونا ننظر إلى هذا كمثال:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
الدليل النهائي لتبديل التعبيرات في Java 13 ميزات جديدة أخرى:
  1. String:

    transform(Function f)- تطبيق الوظيفة المقدمة على سلسلة. قد لا تكون النتيجة سلسلة.
    indent(int x)- يضيف مسافات x إلى السلسلة. إذا كانت المعلمة سلبية، فسيتم إزالة هذا العدد من المسافات البادئة (إن أمكن).

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

  3. ظهرت فئة جديدة -CompactNumberFormat لتنسيق الرقم العشري في شكل مضغوط. مثال على هذا النموذج المضغوط هو 1M بدلاً من 1,000,000. وبالتالي، مطلوب اثنين فقط بدلاً من تسعة أحرف.

  4. هناك أيضًا قيمة جديدة لها قيمتان - LONG و SHORT.enumNumberFormatStyle

  5. InputStream حصلت على الطريقة skipNBytes(long n) : تخطي العدد n من البايتات من دفق الإدخال.

روابط جافا 12 مثيرة للاهتمام:

جافا 13

العالم لا يقف ساكنًا، بل يتحرك، ويتطور، تمامًا مثل Java - Java 13. من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 2 - 3

كتلة النص

لقد عانت Java دائمًا قليلاً عندما يتعلق الأمر بتعريف السلاسل. إذا أردنا تحديد سطر بمسافة أو فاصل أسطر أو اقتباس أو أي شيء آخر، فقد تسبب ذلك في بعض الصعوبات، لذلك كان علينا استخدام أحرف خاصة: على سبيل المثال، \n لفاصل أسطر، أو الهروب من بعض الأسطر بحد ذاتها. يؤدي هذا إلى تقليل إمكانية قراءة الكود بشكل كبير ويستغرق وقتًا إضافيًا عند كتابة مثل هذا السطر. يصبح هذا ملحوظًا بشكل خاص عند كتابة سلاسل تعرض JSON وXML وHTML وما إلى ذلك. ونتيجة لذلك، إذا أردنا كتابة Json صغير، فسيبدو كما يلي:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
ثم يأتي Java 13 إلى المشهد ويقدم لنا حله في شكل علامات اقتباس مزدوجة ثلاثية قبل النص وبعده (والتي أطلقوا عليها كتل النص). دعونا نلقي نظرة على مثال json السابق باستخدام هذا الابتكار:
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
أبسط بكثير وأكثر وضوحا، أليس كذلك؟ كما تمت إضافة Stringثلاث طرق جديدة لإدارة هذه الكتل على التوالي:
  • stripIndent(): إزالة المسافات العشوائية من السلسلة. يعد هذا مفيدًا إذا كنت تقرأ سلاسل متعددة الأسطر وتريد تطبيق نفس النوع من استبعاد المسافات البيضاء العشوائية الذي يحدث مع إعلان صريح (محاكاة المترجم بشكل أساسي لإزالة المسافات البيضاء العشوائية)؛
  • formatted(Object... args ): مشابه لـ format(String format, Object... arg)، ولكن للكتل النصية؛
  • translateEscapes(): إرجاع سلسلة مع تسلسلات الهروب (مثل \r) مترجمة إلى قيمة Unicode المقابلة.

تحسين التبديل

تم تقديم تعبيرات التبديل في Java 12، وقام 13 بتحسينها. في 12 تحدد قيم الإرجاع باستخدام الفاصل. في 13، تم استبدال قيمة الإرجاع بالعائد. الآن يمكن إعادة كتابة تعبير التبديل الذي كان لدينا في قسم Java 12 على النحو التالي:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
على الرغم من أنه كان من الطبيعي بالنسبة لنا نحن المبرمجين المطلعين على Java أن نقبل الاستراحة، إلا أنه كان غريبًا تمامًا. ما هو الكسر الحقيقي الذي يحاول أن يخبرني به؟ تعد الكلمة الرئيسية الجديدة (الجديدة نسبيًا) أكثر وضوحًا وقد تظهر في أماكن أخرى في المستقبل حيث يتم إرجاع القيم. بالنسبة لأولئك المهتمين بشدة بهذا الموضوع، أنصحهم بالتعرف على هذه المواد:

أرشيفات أقراص CDS الديناميكية

CDS - مشاركة بيانات الفصل. يسمح لك بحزم مجموعة من الفئات شائعة الاستخدام في أرشيف يمكن تحميله لاحقًا بواسطة مثيلات JVM متعددة. لماذا نحتاج هذا؟ الحقيقة هي أنه في عملية تحميل الفئات، يقوم JVM بالكثير من الإجراءات كثيفة الاستخدام للموارد، مثل قراءة الفئات، وتخزينها في الهياكل الداخلية، والتحقق من صحة فئات القراءة، والبحث عن الفئات التابعة وتحميلها، وما إلى ذلك وفقط بعد كل هذا تصبح الفصول جاهزة للعمل. من المفهوم أنه يتم إهدار الكثير من الموارد، نظرًا لأن مثيلات JVM يمكنها غالبًا تحميل نفس الفئات. على سبيل المثال سلسلة، LinckedList، عدد صحيح. حسنًا، أو فئات من نفس التطبيق، وكل هذه موارد. إذا قمنا بتنفيذ جميع الخطوات اللازمة مرة واحدة فقط ثم وضعنا الفئات المعاد تصميمها في أرشيف يمكن تحميله في ذاكرة العديد من أجهزة JVM، فقد يؤدي ذلك إلى توفير مساحة الذاكرة بشكل كبير وتقليل وقت بدء تشغيل التطبيق. في الواقع، تتيح أقراص CDS إمكانية إنشاء مثل هذا الأرشيف. يسمح Java 9 فقط بإضافة فئات النظام إلى الأرشيف. Java 10 - تضمين فئات التطبيقات في الأرشيف. يتكون إنشاء هذا الأرشيف من:
  • إنشاء قائمة الفئات التي تم تحميلها بواسطة التطبيق؛
  • إنشاء أرشيف تشتد الحاجة إليه مع الفئات التي وجدناها.
يعمل الابتكار في Java 13 على تحسين أقراص CDS بحيث يمكنها إنشاء أرشيف عند إنهاء التطبيق. وهذا يعني أنه سيتم الآن دمج الخطوتين أعلاه في خطوة واحدة. ونقطة أخرى مهمة: سيتم إضافة الفئات التي تم تحميلها أثناء تشغيل التطبيق فقط إلى الأرشيف. بمعنى آخر، تلك الفئات التي لا تزال موجودة في application.jar، ولكن لسبب ما لم يتم تحميلها، لن تتم إضافتها إلى الأرشيف.

تحديث واجهة برمجة تطبيقات المقبس

تعد واجهة برمجة تطبيقات المقبس ( java.net.Socket وjava.net.ServerSocket ) جزءًا لا يتجزأ من Java منذ بدايتها، ولكن لم يتم تحديث المقابس مطلقًا خلال العشرين عامًا الماضية. كانت مكتوبة بلغة C وJava، وكانت ضخمة جدًا ويصعب صيانتها. لكن Java 13 قررت إجراء تعديلاتها الخاصة على هذا الأمر برمته واستبدلت التنفيذ الأساسي. الآن، بدلاً من PlainSocketImpl، تم استبدال واجهة الموفر بـ NioSocketImpl . يعتمد هذا التنفيذ المشفر الجديد على نفس البنية التحتية الخلفية مثل java.nio . بشكل أساسي، يستخدم الفصل ذاكرة التخزين المؤقت java.util.concurrent وآلية القفل (التي تعتمد على المقطع) بدلاً من الأساليب المتزامنة. لم يعد يتطلب تعليمات برمجية أصلية، مما يسهل النقل إلى منصات مختلفة. لا يزال لدينا طريقة للعودة إلى استخدام PlainSocketImpl ، ولكن من الآن فصاعدًا سيتم استخدام NioSocketImpl افتراضيًا .

عودة الذاكرة لـ ZGC

كما نتذكر، تم تقديم أداة تجميع البيانات المهملة Z في Java 11 كآلية لجمع البيانات المهملة ذات زمن وصول منخفض بحيث لا يتجاوز توقف GC المؤقت 10 مللي ثانية أبدًا. ولكن في الوقت نفسه، على عكس نقاط GC HotSpots الافتراضية الأخرى، مثل Shenandoah وG1، يمكنها إعادة الذاكرة الديناميكية غير المستخدمة إلى نظام التشغيل. يضيف هذا التعديل قدرة J هذه إلى ZGC. وفقًا لذلك، نحصل على مساحة أقل للذاكرة مع تحسين الأداء، وتقوم ZGC الآن بإرجاع الذاكرة غير الملتزم بها إلى نظام التشغيل بشكل افتراضي حتى يتم الوصول إلى الحد الأدنى لحجم الكومة المحدد. شيء آخر: لدى ZGC الآن الحد الأقصى لحجم الكومة المدعومة وهو 16 تيرابايت. في السابق، كان الحد الأقصى هو 4 تيرابايت. ابتكارات أخرى:
  1. javax.security- إضافة خاصية jdk.sasl.disabledMechanismsتعطيل آليات SASL.
  2. java.nio- تمت إضافة طريقة FileSystems.newFileSystem (Path, Map <String,?>)- على التوالي، لإنشاء ملف جديد.
  3. تحتوي الفصول الدراسية الآن على طرق java.nioمطلقة (بدلاً من النسبية) . وهي، مثل الفئة المجردة الأساسية ، تتضمن طريقة لاسترداد جزء من المخزن المؤقت.getsetBufferslice()
  4. تمت إضافة javax.xml.parsersطرق لإنشاء مصانع DOM وSAX (مع دعم مساحة الاسم).
  5. تم تحديث دعم Unicode إلى الإصدار 12.1.
روابط مثيرة للاهتمام في Java 13:

نتائج

يمكننا مراجعة الابتكارات المعلن عنها في Java 14، ولكن نظرًا لأنها سترى النور قريبًا - من المقرر إصدار JDK 14 في 17 مارس 2020، سيكون من الأفضل إجراء مراجعة منفصلة وكاملة له فور إصداره . أود أيضًا أن ألفت انتباهك إلى حقيقة أنه في لغات البرمجة الأخرى التي بها فترات راحة طويلة بين الإصدارات، مثل Python 2–3، لا يوجد توافق: أي إذا تمت كتابة الكود بلغة Python 2، فسوف بحاجة إلى العمل الجاد لترجمتها إلى 3. تعتبر Java مميزة في هذا الصدد لأنها متوافقة للغاية مع الإصدارات السابقة. وهذا يعني أن برنامج Java 5 أو 8 الخاص بك مضمون للتشغيل على جهاز Java 8-13 الظاهري - مع بعض الاستثناءات التي لا داعي للقلق بشأنها في الوقت الحالي. من الواضح أن هذا لا يحدث في الاتجاه المعاكس: على سبيل المثال، إذا كان تطبيقك يستخدم وظائف Java 13 التي لا تتوفر ببساطة في Java 8 JVM. هذا كل ما لدي لهذا اليوم، مع احترامي لأولئك الذين قرأوا حتى هذه اللحظة)) من 8 إلى 13: نظرة عامة كاملة على إصدارات جافا.  الجزء 2 - 5
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION