JavaRush /Java Blogu /Random-AZ /8-dən 13-ə qədər: Java versiyalarının tam icmalı. 2-ci hi...

8-dən 13-ə qədər: Java versiyalarının tam icmalı. 2-ci hissə

Qrupda dərc edilmişdir
Bu məqalə mənim Java 8-13 versiyalarındakı yenilikləri nəzərdən keçirməyimin ikinci hissəsidir. Birinci hissə buradadır . Daha çox uzatmadan, davam edək: yeni JDK-nın buraxıldığı 25 sentyabr 2018-ci ilə qədər:

Java 11

8-dən 13-ə qədər: Java versiyalarının tam icmalı.  Hissə 2 - 1

var (lambda ilə)

Bundan sonra biz lambda parametrlərinin növlərini təyin edə və ya lambda ifadəsi yazarkən onları buraxa bilərik (dolaylı olaraq yazılmış lambda ifadələri):
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
Tam dəyişən növünün adını yazmadan lambda parametrlərinə annotasiyalar da əlavə edə bilərsiniz:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC işləməyən yeni zibil toplayıcısıdır. Yeni yaddaş ayırır, lakin onu heç vaxt yenidən başlatmır. ZGC yüksək ötürmə qabiliyyəti və aşağı gecikmə ilə böyük həcmdə yaddaşı idarə etməyi vəd edir (ZGC yalnız 64 bitlik platformalarda mövcuddur). İstinad Boyama - ZGC göstərici rəngləmə adlanan texnika ilə 64 bitlik göstəricilərdən istifadə edir. Rəngli göstəricilər yığındakı obyektlər haqqında əlavə məlumat saxlayır. Yaddaş parçalandıqda, bu, GC-nin yeni ayırma üçün yer tapması lazım olduqda performansın pisləşməsinin qarşısını alır. ZGC istifadə edərək zibil toplama aşağıdakı addımlardan ibarətdir:
  1. dünya dayanır: biz yığındakı obyektlərə çatmaq üçün başlanğıc nöqtələri axtarırıq (məsələn, yerli dəyişənlər və ya statik sahələr);
  2. kök keçidlərdən başlayaraq obyekt qrafiklərinin kəsişməsi. Biz çatdığımız hər bir obyekti qeyd edirik (ZGC obyekt qrafiki ilə gəzir və mövcud obyektləri qeyd edərək rəngli markerləri yoxlayır);
  3. zəif keçidlər kimi bəzi kənar halların idarə edilməsi;
  4. canlı obyektləri hərəkət etdirmək, ayrılmağı sürətləndirmək üçün yığının böyük sahələrini azad etmək.
  5. köçürmə mərhələsi başlayanda ZGC yığını səhifələrə bölür və hər dəfə bir səhifə işləyir;
  6. ZGC istənilən köklərin hərəkətini bitirir və hərəkətin qalan hissəsi baş verir.
Bu mövzu çox mürəkkəb və qarışıqdır. Ətraflı müzakirə üçün ayrıca məqalə lazımdır, ona görə də onu burada buraxacağam:

Epsilon GC

Epsilon yaddaşın ayrılmasını idarə edən, lakin heç bir real yaddaş bərpa mexanizmini həyata keçirməyən zibil toplayıcısıdır. Mövcud Java yığını tükəndikdən sonra JVM bağlanacaq. Yəni, bu zibil toplayıcısı ilə istinadla əlaqə yaratmadan sonsuz massivdə obyekt yaratmağa başlasanız, proqram OutOfMemoryError ilə qəzaya uğrayacaq (və əgər hər hansı digəri varsa, o, obyektləri istinadlar olmadan təmizləyəcəyi üçün olmayacaq) . Niyə lazımdır? Bunun səbəbi:
  1. Performans testi.
  2. Yaddaş təzyiq testi.
  3. VM interfeysi sınaqdan keçirilir.
  4. Son dərəcə qısa iş.
  5. Son enmə gecikmə təkmilləşdirmələri.
  6. Son buraxılış məhsuldarlığı təkmilləşdirmələri.
Faydalı bağlantılar: Digər yeniliklər:
  1. ByteArrayOutputStreamvoid writeBytes(byte [])arqumentdən bütün baytları yazan bir üsul əldə etdi OutputStream.
  2. FileReaderFileWriterCharset-i təyin etməyə imkan verən yeni konstruktorlar əldə etdi.
  3. Pathiki yeni metod əldə etdi, bir sətir arqumentindən bir yol və ya sətir ardıcıllığını of(String, String [])qaytarır ki, onlar birləşdirildikdə yol sətrini təşkil edir və : URI-dən Path qaytarır.Pathof(URI)
  4. Pattern— verilmiş giriş sətirinin verilmiş nümunəyə uyğun olub-olmadığını yoxlayan metod asMatchPredicate()(bu, məsələn, axındakı məlumatları süzgəcdən keçirə bilməniz üçün müntəzəm ifadədən istifadə edərək predikat yaratmağa imkan verirmi) əldə etdi.
  5. StringMən bir çox faydalı üsul seçdim, məsələn:
    • String strip(): bizə bu sətir olan sətri qaytaracaq, sətrin əvvəlində və sonunda bütün boşluqlar silinmiş (trim() ilə oxşar, lakin boşluqları fərqli müəyyən edir);
    • String stripLeading(): bizə bu sətir olan sətri qaytaracaq, sətirdən istənilən aparıcı boşluqları çıxaracaq;
    • String stripTrailing(): sətrin sonundakı boşluqları silməklə bizə bu sətir olan sətri qaytaracaq;
    • Stream lines()Stream: bizi , bu sətirdən Stringçıxarılan, sətir ayırıcıları ilə ayrılaraq qaytaracaq ;
    • String repeat(int): bizə bir neçə dəfə təkrarlanan bu sətri birləşdirən sətir qaytaracaq.
    • boolean isBlank(): sətir boşdursa və ya yalnız boşluqlardan ibarətdirsə doğru, əks halda false qaytaracaq.
  6. Thread— destroy() və stop(Throwable) üsulları silindi.
  7. Filesbir sıra yeni üsullar əldə etdi:
    • String readString(Path): UTF-8 kodlaşdırmasından istifadə edərək baytlardan simvollara deşifrə edərkən fayldan bütün məlumatları sətirdə oxuyur;
    • String readString(Path, Charset): yuxarıdakı üsulda olduğu kimi, baytlardan simvollara deşifrənin göstərilən Charsetdən istifadə etməklə baş verməsi fərqi ilə;
    • Path writeString (Path, CharSequence, OpenOption []): Fayla simvollar ardıcıllığını yazır. Simvollar UTF-8 kodlaşdırmasından istifadə edərək baytlara kodlanır;
    • Path writeString(Path, CharSequence,Charset, OpenOption []): Yuxarıdakı üsulla eyni üsul, Charset-də göstərilən kodlaşdırmadan istifadə etməklə yalnız simvollar baytlara kodlanır.
Bunlar ən maraqlı API yenilikləri idi (təvazökar fikrimcə), burada daha ətraflı nəzərdən keçirmək üçün bir neçə material var:

Java 12

Altı ay keçir və biz Java-nın təkamülünün növbəti mərhələsini görürük. Beləliklə, bilik kürəyini çıxarmaq və qazmaq vaxtıdır. 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  2-2 hissə

G1-i yeniləyin

G1 üçün aşağıdakı təkmilləşdirmələr edildi:
  1. İstifadə edilməmiş ayrılmış yaddaşı bərpa edin

    Java yığın yaddaşında istifadə olunmamış yaddaş (və ya başqa sözlə, qeyri-aktiv) kimi bir şey var. Java 12-də bu problemi həll etmək qərarına gəldilər, indi:

    • G1 yaddaşı tam GC-də və ya paralel dövrə zamanı yığından qaytarır; G1 tam GC-nin qarşısını almağa çalışır və yığın ayrılması əsasında paralel dövrə başlayır. G1-i yığından yaddaşı qaytarmağa məcbur etməli olacağıq.

    Bu təkmilləşdirmə G1 istifadə edilmədikdə yaddaşı yığından ƏS-ə avtomatik qaytarmaqla performansa diqqət yetirir.

  2. Pauza vaxtı keçdikdə qarışıq kolleksiyaların dayandırılması

    G1 zibilin yığılması üçün tələb olunan işin həcmini seçmək üçün analiz mühərrikindən istifadə edir. Dəsti təyin etdikdən və təmizləməyə başladıqdan sonra dayanmadan canlı obyektləri toplayır. Bu, zibil toplayıcının fasilə vaxtı hədəfini aşmasına səbəb olur. Əslində, bu problem təkmilləşdirmə yolu ilə həll olunur, çünki növbəti addımın icra müddəti ağlabatan hədləri aşarsa, bu addım dayandırıla bilər.

Mikrobenchmark

Java 12 mikrobençmarkinq testlərini təqdim etdi ki, JVM performansı mövcud etalonlardan istifadə etməklə asanlıqla sınaqdan keçirilsin. Bu, JVM-in özündə işləmək istəyən hər kəs üçün çox faydalı olardı. Əlavə edilmiş testlər Java Microbenchmark Harness (JMH) istifadə edərək yaradılmışdır. Bu testlər JVM-də davamlı performans testinə imkan verir. JEP 230 təxminən 100 testin tətbiqini təklif edir, Java-nın yeni versiyaları buraxıldıqca yeni testlər təqdim olunur. Budur əlavə edilən testlərə bir nümunə .

Şenandoah

Bu, aşağı cavab müddətini təmin etmək məqsədi daşıyan zibil kolleksiyası (GC) alqoritmidir (aşağı limit 10-500 ms-dir). Bu, Java mövzuları ilə eyni vaxtda təmizləmə işləri apararkən GC fasilə vaxtını azaldır. Shenandoah-da fasilə vaxtı yığın ölçüsündən asılı deyil. Bu o deməkdir ki, pauza vaxtı yığınınızın ölçüsündən asılı olmayaraq eyni olacaq. Bu eksperimental xüsusiyyətdir və OpenJDK-nın standart (Oracle) quruluşuna daxil edilməyib.

Keçiri təkmilləşdirin

Java 12 nümunə uyğunluğu üçün keçid ifadələrini təkmilləşdirmişdir. Yeni L → sintaksisi təqdim edildi. Budur yeni keçidin əsas məqamlarının siyahısı :
  1. Yeni sintaksis səhvlərin qarşısını almaq üçün fasilə ifadəsinə ehtiyacı aradan qaldırır.
  2. Keçid ifadələri artıq uğursuz deyil.
  3. Bundan əlavə, biz bir etiketdə çoxlu sabitləri təyin edə bilərik.
  4. defolt hal indi keçid ifadələrində tələb olunur.
  5. break registrdən dəyərləri qaytarmaq üçün Switch ifadələrində istifadə olunur (əslində keçid dəyərləri qaytara bilər).
Buna misal kimi baxaq:
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-də ifadələri dəyişdirmək üçün qəti bələdçi Digər yeni xüsusiyyətlər:
  1. String:

    transform(Function f)- Təqdim olunan funksiyanı sətirə tətbiq edir. Nəticə sətir olmaya bilər.
    indent(int x)— sətirə x boşluq əlavə edir. Parametr mənfi olarsa, bu sayda aparıcı boşluqlar silinəcək (mümkünsə).

  2. Files- kimi bir üsul tutdu mismatch(), bu da öz növbəsində iki faylın məzmununda ilk uyğunsuz baytın mövqeyini tapıb qaytarır və ya uyğunsuzluq yoxdursa -1L.

  3. Yeni bir sinif meydana çıxdı -CompactNumberFormat yığcam formada onluq ədədi formatlaşdırmaq üçün. Bu yığcam formanın nümunəsi 1.000.000 əvəzinə 1M-dir.Beləliklə, doqquz simvol əvəzinə yalnız iki iki tələb olunur.

  4. İki dəyəri olan yenisi də var - UZUN və QISA .enumNumberFormatStyle

  5. InputStream metodu əldə etdim skipNBytes(long n) : giriş axınından n-ci bayt sayını atlayın.

Maraqlı Java 12 bağlantıları:

Java 13

Dünya bir yerdə dayanmır, hərəkət edir, inkişaf edir, Java - Java 13 kimi. 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  2-3 hissə

Mətn bloku

Sətirləri təyin edərkən Java həmişə bir az əziyyət çəkmişdir. Boşluq, sətir sonu, sitat və ya başqa bir şey olan bir sətri təyin etmək lazımdırsa, bu, bəzi çətinliklərə səbəb oldu, buna görə də xüsusi simvollardan istifadə etməli olduq: məsələn, sətir kəsilməsi üçün \n və ya sətirdən bir neçəsini qaçırmaq özü. Bu, kodun oxunuşunu əhəmiyyətli dərəcədə azaldır və belə bir sətir yazarkən əlavə vaxt tələb edir. Bu, JSON, XML, HTML və s. əks etdirən sətirlər yazarkən xüsusilə nəzərə çarpır. Nəticədə kiçik bir Json yazmaq istəsək, bu belə görünəcək:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
Və sonra Java 13 səhnəyə çıxır və bizə mətndən əvvəl və sonra üçqat qoşa dırnaq şəklində həllini təklif edir (bunu mətn blokları adlandırırlar). Bu yenilikdən istifadə edərək əvvəlki json nümunəsinə baxaq:
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
Daha sadə və aydındır, elə deyilmi? StringBu blokları idarə etmək üçün müvafiq olaraq üç yeni üsul əlavə edildi :
  • stripIndent(): Sətirdən təsadüfi boşluqları silir. Bu, çoxsətirli sətirləri oxuyursunuzsa və açıq bəyannamə ilə baş verən eyni növ təsadüfi boşluq istisnasını tətbiq etmək istəyirsinizsə faydalıdır (əsasən təsadüfi boşluqları silmək üçün tərtibçini simulyasiya edir);
  • formatted(Object... args ): oxşar format(String format, Object... arg), lakin mətn blokları üçün;
  • translateEscapes(): Müvafiq Unicode dəyərinə tərcümə edilmiş qaçış ardıcıllığı (məsələn, \r) ilə sətri qaytarır.

Keçiri təkmilləşdirin

Keçid ifadələri Java 12-də təqdim edildi və 13-ü onları təkmilləşdirir. 12-də fasilədən istifadə edərək qaytarma dəyərlərini təyin edirsiniz. 13-də qaytarma dəyəri gəlirlə əvəz edilmişdir. İndi Java 12 bölməsində malik olduğumuz keçid ifadəsi belə yenidən yazıla bilər:
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 ilə artıq tanış olan biz proqramçılar üçün fasiləni qəbul etmək normal olsa da, bu, olduqca qəribə idi. Mənə deməyə çalışan həqiqət nədir? Yeni (nisbətən yeni) gəlir açar sözü daha aydındır və gələcəkdə dəyərlərin qaytarıldığı başqa yerlərdə görünə bilər. Bu mövzu ilə dərindən maraqlananlar üçün bu materiallarla tanış olmağı məsləhət görürəm:

Dinamik CDS Arxivləri

CDS - Sinif Məlumat Paylaşımı. Tez-tez istifadə olunan siniflər toplusunu daha sonra birdən çox JVM nümunəsi tərəfindən yüklənə bilən arxivə yığmağa imkan verir. Bu bizə niyə lazımdır? Fakt budur ki, siniflərin yüklənməsi prosesində JVM kifayət qədər resurs tələb edən hərəkətləri yerinə yetirir, məsələn, dərsləri oxumaq, onları daxili strukturlarda saxlamaq, oxunan siniflərin düzgünlüyünü yoxlamaq, asılı sinifləri axtarmaq və yükləmək və s. ., və yalnız bütün bunlardan sonra dərslər işə hazırdır. JVM nümunələri tez-tez eyni sinifləri yükləyə bildiyi üçün çoxlu resurs sərf olunur. Məsələn, String, LinkedList, Integer. Yaxşı və ya eyni tətbiqin sinifləri və bunların hamısı resurslardır. Bütün lazımi addımları yalnız bir dəfə yerinə yetirsək və sonra yenidən dizayn edilmiş sinifləri bir neçə JVM-in yaddaşına yükləmək mümkün olan arxivə yerləşdirsək, bu, yaddaş sahəsinə əhəmiyyətli dərəcədə qənaət edə və tətbiqin işə salınma vaxtını azalda bilər. Əslində, CDS məhz belə bir arxiv yaratmağa imkan verir. Java 9 yalnız sistem siniflərinin arxivə əlavə edilməsinə icazə verdi. Java 10 - proqram siniflərini arxivə daxil edin. Belə bir arxivin yaradılması aşağıdakılardan ibarətdir:
  • proqram tərəfindən yüklənmiş siniflərin siyahısını yaratmaq;
  • tapdığımız siniflərlə çox lazımlı arxiv yaratmaq.
Java 13-dəki yenilik CDS-i təkmilləşdirir ki, proqram dayandırıldıqda arxiv yarada bilsin. Bu o deməkdir ki, yuxarıdakı iki addım indi bir yerdə birləşdiriləcək. Və daha bir vacib məqam: yalnız proqram işləyərkən yüklənmiş siniflər arxivə əlavə olunacaq. Başqa sözlə, hələ də application.jar-da olan, lakin nədənsə yüklənməmiş siniflər arxivə əlavə edilməyəcək.

Socket API-i yeniləyin

Socket API ( java.net.Socket və java.net.ServerSocket ) yarandığı gündən Java-nın ayrılmaz hissəsidir, lakin son iyirmi ildə soketlər heç vaxt yenilənməyib. C və Java dillərində yazılmışdır, onlar çox, çox həcmli və saxlanması çətin idi. Lakin Java 13 bütün bu məsələyə öz düzəlişlərini etmək qərarına gəldi və əsas tətbiqi əvəz etdi. İndi PlainSocketImpl əvəzinə provayder interfeysi NioSocketImpl ilə əvəz edilmişdir . Bu yeni kodlaşdırılmış tətbiq java.nio ilə eyni arxa-end infrastruktura əsaslanır . Əsasən sinif sinxronlaşdırılmış metodlardan çox java.util.concurrent bufer keşindən və kilidləmə mexanizmindən (seqment əsaslı) istifadə edir. Artıq yerli kod tələb etmir, bu da müxtəlif platformalara keçidi asanlaşdırır. Yenə də PlainSocketImpl istifadəsinə qayıtmaq üçün bir yolumuz var , lakin bundan sonra NioSocketImpl standart olaraq istifadə olunur .

ZGC üçün yaddaşın qaytarılması

Xatırladığımız kimi, Z zibil toplayıcısı Java 11-də GC fasiləsi heç vaxt 10 ms-dən çox olmaması üçün aşağı gecikmə müddəti olan zibil toplama mexanizmi kimi təqdim edilmişdir. Lakin eyni zamanda, Shenandoah və G1 kimi digər virtual GC HotSpot-lardan fərqli olaraq, o, istifadə olunmamış dinamik yaddaşı ƏS-ə qaytara bilər. Bu modifikasiya bu J qabiliyyətini ZGC-yə əlavə edir. Müvafiq olaraq, təkmilləşdirilmiş performansla yanaşı, azaldılmış yaddaş izi əldə edirik və ZGC indi müəyyən edilmiş minimum yığın ölçüsünə çatana qədər defolt olaraq əməliyyat sisteminə bağlanmamış yaddaşı qaytarır. Daha bir şey: ZGC indi 16 TB-lik maksimum dəstəklənən yığın ölçüsünə malikdir. Əvvəllər 4TB limit idi. Digər yeniliklər:
  1. javax.security- jdk.sasl.disabledMechanismsSASL mexanizmlərini söndürmək üçün bir xüsusiyyət əlavə etdi.
  2. java.nioFileSystems.newFileSystem (Path, Map <String,?>)- müvafiq olaraq yeni fayl yaratmaq üçün metod əlavə edildi .
  3. İndi siniflərdə java.niomütləq (nisbidən fərqli olaraq) getset-metodlar var. Onlar, əsas mücərrəd sinif kimi Buffer, slice()buferin bir hissəsini almaq üçün bir metodu ehtiva edir.
  4. DOM və SAX zavodlarının yaradılması üçün əlavə javax.xml.parsersüsullar (ad sahəsi dəstəyi ilə).
  5. Unicode dəstəyi 12.1 versiyasına yeniləndi.
Java 13-də maraqlı bağlantılar:

Nəticələr

Java 14-də elan edilmiş yenilikləri nəzərdən keçirə bilərik, lakin o, tezliklə işığı görəcəyi üçün - JDK 14-ün 17 mart 2020-ci ildə buraxılması planlaşdırıldığından, buraxıldıqdan dərhal sonra onun ayrıca, tam nəzərdən keçirilməsi daha yaxşı olardı. . Diqqətinizi ona da çatdırmaq istərdim ki, buraxılışlar arasında uzun fasilələr olan digər proqramlaşdırma dillərində, məsələn, Python 2–3-də uyğunluq yoxdur: yəni kod Python 2-də yazılıbsa, siz onu 3-ə çevirmək üçün çox çalışmaq lazımdır. Java bu baxımdan xüsusidir, çünki o, son dərəcə geriyə uyğundur. Bu o deməkdir ki, sizin Java 5 və ya 8 proqramınızın Java 8-13 virtual maşınında işləməsinə zəmanət verilir—bir neçə istisna olmaqla, hələlik narahat olmağa ehtiyac yoxdur. Aydındır ki, bunun əksi işləmir: məsələn, tətbiqiniz Java 8 JVM-də sadəcə mövcud olmayan Java 13 funksiyalarından istifadə edirsə. Bu gün üçün əlimdə olan budur, bu günə kimi oxuyanlara hörmətim var)) 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  2-5 hissə
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION