JavaRush /בלוג Java /Random-HE /מ-8 עד 13: סקירה מלאה של גרסאות Java. חלק 2

מ-8 עד 13: סקירה מלאה של גרסאות Java. חלק 2

פורסם בקבוצה
מאמר זה הוא החלק השני של סקירת החידושים שלי בגרסאות Java 8-13. החלק הראשון כאן . בלי להכביר מילים, בואו נמשיך: ל-25 בספטמבר 2018, אז יצא ה-JDK החדש:

Java 11

מ-8 עד 13: סקירה מלאה של גרסאות Java.  חלק 2 - 1

var (בלמבדה)

מעתה והלאה, נוכל לציין את סוגי פרמטרי למבדה או להשמיט אותם בעת כתיבת ביטוי למבדה (ביטויי למבדה מוקלדים באופן מרומז):
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
אתה יכול גם להוסיף הערות לפרמטרים למבדה מבלי לכתוב את שם סוג המשתנה המלא:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC הוא אספן אשפה חדש שלא עובד. הוא מקצה זיכרון חדש אך לעולם אינו מפעיל אותו מחדש. ZGC מבטיחה לנהל כמויות גדולות של זיכרון עם תפוקה גבוהה והשהייה נמוכה (ZGC זמין רק בפלטפורמות של 64 סיביות). צביעת התייחסות - ZGC משתמשת במצביעים של 64 סיביות בטכניקה הנקראת צביעת מצביע. מצביעים צבעוניים מאחסנים מידע נוסף על עצמים בערימה. כאשר הזיכרון מפוצל, זה עוזר למנוע ירידה בביצועים כאשר ה-GC צריך למצוא מקום להקצאה חדשה. איסוף אשפה באמצעות ZGC מורכב מהשלבים הבאים:
  1. עוצרים בעולם: אנו מחפשים נקודות התחלה כדי להגיע לאובייקטים על הערימה (כגון משתנים מקומיים או שדות סטטיים);
  2. חיתוך של גרפי אובייקטים החל מקישורי שורש. אנו מסמנים כל אובייקט אליו אנו מגיעים (ZGC עובר בגרף האובייקטים ובוחן את הסמנים הצבעוניים, מסמן אובייקטים זמינים);
  3. טיפול בכמה מקרי קצה, כגון חוליות חלשות;
  4. הזזת חפצים חיים, שחרור שטחים גדולים מהערימה כדי להאיץ את ההקצאה.
  5. כאשר שלב המעבר מתחיל, ZGC מפצלת את הערימה לדפים ועובדת עמוד אחד בכל פעם;
  6. ה-ZGC מסיים את התנועה של כל השורשים ושאר התנועה מתרחשת.
הנושא הזה מאוד מורכב ומבלבל. דיון מפורט ידרוש מאמר נפרד, אז אני פשוט אשאיר אותו כאן:

אפסילון GC

אפסילון הוא אוסף אשפה שמטפל בהקצאת זיכרון אך אינו מיישם שום מנגנון שחזור זיכרון אמיתי. לאחר שתמוצה ערימת ה-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): מחזיר Path מ-URI.
  4. Pattern— קיבלה שיטה asMatchPredicate()שבודקת אם מחרוזת קלט נתונה תואמת לדפוס נתון (האם היא מאפשרת לך ליצור פרדיקט באמצעות ביטוי רגולרי כדי שתוכל, למשל, לסנן נתונים בזרם).
  5. Stringאספתי שיטות שימושיות רבות, כגון:
    • String strip(): יחזיר לנו מחרוזת שהיא המחרוזת הזו, כשכל הרווחים בתחילת המחרוזת ובסוף הוסרו (בדומה ל-trim(), אבל מגדיר רווחים בצורה שונה);
    • String stripLeading(): יחזיר לנו את המחרוזת שהיא המחרוזת הזו, תוך הסרת רווחים מובילים מהמחרוזת;
    • String stripTrailing(): יחזיר לנו את המחרוזת שהיא המחרוזת הזו, תוך הסרת רווחים בקצה המחרוזת;
    • Stream lines(): יחזיר אותנו Streamמ- String, מופק מהמחרוזת הזו, מופרדים על ידי מפרידי שורות;
    • String repeat(int): יחזיר לנו מחרוזת שהיא שרשור של מחרוזת זו, שחוזרת על עצמה מספר פעמים.
    • boolean isBlank(): יחזיר true אם המחרוזת ריקה או מכילה רק רווחים, אחרת false.
  6. Thread- methods destroy() ו-stop(Throwable) הוסרו.
  7. Filesקיבלתי מספר שיטות חדשות:
    • String readString(Path): קורא את כל הנתונים מקובץ לתוך מחרוזת, תוך פענוח מבייטים לתווים באמצעות קידוד UTF-8;
    • String readString(Path, Charset): זהה לשיטה שלמעלה, עם ההבדל שפענוח מבייטים לתווים מתרחש באמצעות ערכת התווים שצוינה;
    • Path writeString (Path, CharSequence, OpenOption []): כותב רצף של תווים לקובץ. תווים מקודדים לבייטים באמצעות קידוד UTF-8;
    • Path writeString(Path, CharSequence,Charset, OpenOption []): אותה שיטה כמו לעיל, רק תווים מקודדים לבייטים באמצעות הקידוד שצוין ב-Charset.
אלו היו חידושי ה-API המעניינים ביותר (לעניות דעתי), הנה כמה חומרים לסקירה מפורטת יותר:

Java 12

שישה חודשים חולפים ואנו רואים את השלב הבא באבולוציה של ג'אווה. אז, הגיע הזמן להוציא את חפירת הידע ולחפור. מ-8 עד 13: סקירה מלאה של גרסאות Java.  חלק 2 - 2

עדכון G1

השיפורים הבאים בוצעו עבור G1:
  1. תבע מחדש זיכרון מוקצה שלא נעשה בו שימוש

    בזיכרון ערימת Java יש דבר כזה זיכרון לא בשימוש (או במילים אחרות, לא פעיל). ב-Java 12 הם החליטו לתקן את הבעיה הזו, עכשיו:

    • G1 מחזיר זיכרון מהערימה ב-GC מלא או במהלך לולאה מקבילה; G1 מנסה למנוע GC מלא ומתחיל לולאה מקבילה על סמך הקצאת הערימה. נצטרך להכריח את G1 להחזיר זיכרון מהערימה.

    שיפור זה מתמקד בביצועים על ידי החזרה אוטומטית של זיכרון מהערימה למערכת ההפעלה כאשר G1 אינו בשימוש.

  2. ביטול אוספים מעורבים כאשר חריגה מזמן ההשהיה

    G1 משתמש במנוע ניתוח כדי לבחור את כמות העבודה הנדרשת לאיסוף אשפה. הוא אוסף חפצים חיים ללא עצירה לאחר הגדרת הסט והתחלת הניקוי. זה גורם לאספן האשפה לחרוג מהיעד של זמן ההשהיה שלו. למעשה, בעיה זו נפתרת על ידי השיפור, שכן אם זמן הביצוע של השלב הבא הוא מעבר לגבולות הסבירים, ניתן להפריע לשלב זה.

Microbenchmark

Java 12 הציגה בדיקות מיקרו-benchmarking כך שניתן לבדוק בקלות את ביצועי JVM באמצעות מדדים קיימים. זה יהיה מאוד שימושי עבור כל מי שרוצה לעבוד על ה-JVM עצמו. הבדיקות שנוספו נוצרות באמצעות Java Microbenchmark Harness (JMH). בדיקות אלו מאפשרות בדיקות ביצועים מתמשכות ב-JVM. JEP 230 מציע הקדמה של כ-100 בדיקות, כאשר בדיקות חדשות הוצגו עם יציאת גרסאות חדשות של Java. הנה דוגמה לבדיקות שנוספו .

שננדואה

זהו אלגוריתם איסוף זבל (GC) שמטרתו להבטיח זמני תגובה נמוכים (הגבול התחתון הוא 10-500 אלפיות השנייה). זה מקטין את זמן ההשהיה של GC כאשר מבצעים עבודת ניקוי במקביל להפעלת שרשורי Java. בשננדואה, זמן ההפסקה אינו תלוי בגודל הערימה. המשמעות היא שזמן ההשהיה יהיה זהה ללא קשר לגודל הערימה שלך. זוהי תכונה ניסיונית ואינה נכללת במבנה הסטנדרטי (Oracle) של OpenJDK.

שפר את המתג

Java 12 שיפר את ביטויי Switch עבור התאמת דפוסים. הוצג תחביר חדש L →. להלן רשימה של נקודות המפתח של המתג החדש :
  1. התחביר החדש מבטל את הצורך בהצהרת break כדי למנוע שגיאות.
  2. ביטויי החלף כבר לא נכשלים.
  3. בנוסף, אנו יכולים להגדיר מספר קבועים בתווית אחת.
  4. רישיון ברירת מחדל נדרש כעת בביטויי מתג.
  5. break משמש בביטויי Switch כדי להחזיר ערכים מהאוגר עצמו (למעשה, מתג יכול להחזיר ערכים).
בואו נסתכל על זה כדוגמה:
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. יש גם אחד חדש enum , NumberFormatStyleשיש לו שני ערכים - LONG ו-SHORT.

  5. InputStream השגתי את השיטה skipNBytes(long n) : דלג על המספר ה-n'י של בתים מזרם הקלט.

קישורי Java 12 מעניינים:

Java 13

העולם לא עומד במקום, הוא זז, הוא מתפתח, בדיוק כמו Java - Java 13. מ-8 עד 13: סקירה מלאה של גרסאות Java.  חלק 2 - 3

בלוק טקסט

Java תמיד סבלה קצת כשזה מגיע להגדרת מחרוזות. אם אנחנו צריכים להגדיר שורה עם רווח, מעבר שורה, ציטוט או משהו אחר, זה גרם לכמה קשיים, אז היינו צריכים להשתמש בתווים מיוחדים: למשל, \n עבור מעבר שורה, או בריחה חלק מהשורה עצמו. זה מקטין משמעותית את קריאות הקוד ולוקח זמן נוסף בכתיבת שורה כזו. זה בולט במיוחד בעת כתיבת מחרוזות שמציגות JSON, XML, HTML וכו'. כתוצאה מכך, אם נרצה לכתוב Json קטן, זה ייראה בערך כך:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
ואז ג'אווה 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 אתה מגדיר ערכי החזרה באמצעות break. ב-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.";
  }
};
למרות שזה היה נורמלי עבורנו המתכנתים שכבר מכירים את ג'אווה לקבל הפסקה, בכל זאת זה היה די מוזר. מה זה שובר אמת לנסות להגיד לי? מילת המפתח החדשה (החדשה יחסית) תשואה ברורה יותר ועשויה להופיע במקומות אחרים בעתיד שבהם ערכים מוחזרים. למי שמתעניין מאוד בנושא זה, אני ממליץ לך להכיר את החומרים הבאים:

ארכיון CDS דינמי

CDS - שיתוף נתונים בכיתה. מאפשר לך לארוז קבוצה של מחלקות בשימוש נפוץ לתוך ארכיון שניתן לטעון מאוחר יותר על ידי מופעי JVM מרובים. למה אנחנו צריכים את זה? העובדה היא שבתהליך טעינת המחלקות, ה-JVM עושה די הרבה פעולות עתירות משאבים, כמו קריאת מחלקות, אחסוןן במבנים פנימיים, בדיקת נכונות מחלקות הקריאה, חיפוש וטעינת מחלקות תלויות וכו'. ., ורק אחרי כל זה השיעורים מוכנים לעבודה. מובן, משאבים רבים מבוזבזים, מכיוון שמופעי JVM יכולים לעתים קרובות לטעון את אותן מחלקות. לדוגמה String, LinckedList, Integer. ובכן, או מחלקות של אותה אפליקציה, וכל אלה הם משאבים. אם ביצענו את כל השלבים הדרושים רק פעם אחת ואז נמקם את המחלקות שעוצבו מחדש בארכיון שניתן לטעון לזיכרון של מספר JVMs, זה יכול לחסוך משמעותית בשטח זיכרון ולהפחית את זמן ההפעלה של האפליקציה. למעשה, CDS מאפשר ליצור בדיוק ארכיון כזה. Java 9 אפשרה להוסיף רק מחלקות מערכת לארכיון. Java 10 - כלול כיתות יישומים בארכיון. יצירת ארכיון כזה מורכבת מ:
  • יצירת רשימה של מחלקות שנטענו על ידי האפליקציה;
  • יצירת ארכיון נחוץ עם השיעורים שמצאנו.
החידוש ב-Java 13 משפר את ה-CDS כך שהוא יכול ליצור ארכיון כאשר האפליקציה מסתיימת. משמעות הדבר היא ששני השלבים שלמעלה ישולבו כעת לאחד. ועוד נקודה חשובה: רק מחלקות שנטענו בזמן שהאפליקציה פעלה יתווספו לארכיון. במילים אחרות, אותן מחלקות שעדיין כלולות ב- application.jar, אך מסיבה כלשהי לא נטענו, לא יתווספו לארכיון.

עדכן את Socket API

ה-Socket API ( java.net.Socket ו-java.net.ServerSocket ) הוא בעצם חלק בלתי נפרד מג'אווה מאז הקמתה, אך שקעים מעולם לא עודכנו בעשרים השנים האחרונות. כתובים ב-C וב-Java, הם היו מאוד מאוד מגושמים וקשים לתחזוקה. אבל Java 13 החליטה לבצע התאמות משלה לכל העניין הזה והחליפה את היישום הבסיסי. כעת, במקום PlainSocketImpl, ממשק הספק מוחלף ב- NioSocketImpl . יישום מקודד חדש זה מבוסס על אותה תשתית עורפית כמו java.nio . בעיקרו של דבר, המחלקה משתמשת ב-java.util.concurrent buffer cache ובמנגנון הנעילה (המבוססים על מקטעים) במקום בשיטות מסונכרנות. זה כבר לא דורש קוד מקורי, מה שמקל על העברה לפלטפורמות שונות. ובכל זאת, יש לנו דרך לחזור להשתמש ב- PlainSocketImpl , אבל מעתה ואילך נעשה שימוש ב- NioSocketImpl כברירת מחדל .

החזרת זיכרון עבור ZGC

כזכור, אספן האשפה Z הוצג ב-Java 11 כמנגנון איסוף אשפה עם חביון נמוך, כך שהשהיית GC לעולם לא תעלה על 10 אלפיות השנייה. אבל יחד עם זאת, בניגוד ל-GC HotSpots וירטואליים אחרים, כמו Shenandoah ו-G1, הוא יכול להחזיר זיכרון דינמי לא בשימוש למערכת ההפעלה. שינוי זה מוסיף את יכולת ה-J הזו ל-ZGC. בהתאם, אנו מקבלים טביעת זיכרון מופחתת יחד עם ביצועים משופרים, ו-ZGC מחזירה כעת זיכרון לא מחויב למערכת ההפעלה כברירת מחדל עד הגעה לגודל הערימה המינימלית שצוינה. דבר נוסף: ל-ZGC יש כעת גודל ערימה מרבי נתמך של 16 TB. בעבר, 4TB היה הגבול. חידושים נוספים:
  1. javax.security- הוסיף מאפיין jdk.sasl.disabledMechanismsכדי להשבית מנגנוני SASL.
  2. java.nio- נוספה שיטה FileSystems.newFileSystem (Path, Map <String,?>)- בהתאמה, ליצירת קובץ חדש.
  3. למחלקות java.nioיש כעת שיטות אבסולוטיות (בניגוד ליחסיות) getושיטות set-. הם, כמו המחלקה המופשטת הבסיסית Buffer, כוללים שיטה slice()לאחזור חלק מהמאגר.
  4. נוספו javax.xml.parsersשיטות ליצירת מפעלי DOM ו-SAX (עם תמיכה במרחב שמות).
  5. תמיכת Unicode עודכנה לגרסה 12.1.
קישורים מעניינים ב-Java 13:

תוצאות

נוכל לעבור על החידושים שהוכרזו ב-Java 14, אבל מכיוון שהוא יראה אור די בקרוב - JDK 14 מתוכנן לצאת ב-17 במרץ 2020, עדיף לערוך סקירה נפרדת ומלאה שלו מיד לאחר יציאתו . אני גם רוצה להסב את תשומת לבך לעובדה שבשפות תכנות אחרות עם הפסקות ארוכות בין מהדורות, כמו Python 2–3, אין תאימות: כלומר, אם הקוד כתוב בפייתון 2, אתה תעשה צריך לעבוד קשה לתרגם את זה ל-3. Java היא מיוחדת בהקשר הזה כי היא מאוד תואמת לאחור. משמעות הדבר היא שתוכנית Java 5 או 8 שלך מובטחת לפעול על מכונה וירטואלית Java 8-13 - עם כמה חריגים שאינך צריך לדאוג לגביהם לעת עתה. ברור שזה לא עובד הפוך: למשל, אם האפליקציה שלך משתמשת בפונקציות Java 13 שפשוט אינן זמינות ב-Java 8 JVM. זה כל מה שיש לי להיום, כבוד למי שקרא עד נקודה זו)) מ-8 עד 13: סקירה מלאה של גרסאות Java.  חלק 2 - 5
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION