Sebagai pembangun Java yang berkelayakan, kita semua tahu bahawa pada asasnya semua objek dicipta pada timbunan. Walau bagaimanapun, masih tiada perkataan mutlak di sini, ia merujuk kepada secara asasnya semuanya.
Semalam semasa temu bual, seorang kawan mengatakan bahawa semua objek dicipta dalam timbunan, dan kemudian mentertawakan penemuduga.
Memulakan teks utama kami, mari bercakap tentang analisis melarikan diri hari ini.
Escape Analysis (Analisis Escape) kini merupakan teknologi pengoptimuman yang agak canggih dalam mesin maya Java. Ini ialah algoritma analisis aliran data global fungsi silang yang boleh mengurangkan beban penyegerakan dan tekanan peruntukan timbunan memori dalam program Java dengan berkesan. Melalui analisis melarikan diri, pengkompil Java Hotspot boleh menganalisis julat penggunaan rujukan objek baharu dan memutuskan sama ada untuk memperuntukkan objek ke timbunan.
Prinsip asas analisis melarikan diri ialah : menganalisis skop dinamik objek Apabila objek ditakrifkan dalam kaedah, ia mungkin dirujuk oleh kaedah luaran, seperti dihantar ke kaedah lain sebagai parameter panggilan kaedah Escape; ia juga boleh diakses oleh utas luaran, seperti menetapkan pembolehubah contoh yang boleh diakses dalam utas lain Ini dipanggil melarikan diri daripada tiada, kaedah melarikan diri ke utas, ia dipanggil objek dari rendah ke tahap pelarian yang berbeza.
Apabila analisis melarikan diri dihidupkan, pengkompil boleh mengoptimumkan kod seperti berikut:
Dalam JVM, anda boleh menentukan sama ada untuk mendayakan analisis melarikan diri melalui parameter berikut:
-XX:+DoEscapeAnalysis
: Menunjukkan menghidupkan analisis melarikan diri (ia dihidupkan secara lalai selepas JDK 1.7). -XX:+DoEscapeAnalysis
:表示开启逃逸分析(JDK 1.7之后默认开启)。
-XX:-DoEscapeAnalysis
-XX:-DoEscapeAnalysis
: Mewakili Matikan analisis melarikan diri. 🎜Penyegerakan benang itu sendiri adalah proses yang agak memakan masa jika analisis escape dapat menentukan bahawa pembolehubah tidak akan terlepas dari utas dan tidak boleh diakses oleh utas lain, maka pastinya tidak akan ada bacaan dan penulisan. daripada pembolehubah ini, langkah penyegerakan yang dilaksanakan pada pembolehubah ini boleh dihapuskan dengan selamat.
Seperti kod berikut:
public void method() { Object o = new Object(); synchronized (o) { System.out.println(o); } }
terkunci 对象o
, tetapi kitaran hayat objek o adalah sama dengan kaedah kaedah(), jadi ia tidak akan diakses oleh utas lain, dan isu keselamatan benang tidak akan berlaku akan disekat semasa fasa kompilasi JIT Dioptimumkan untuk kelihatan seperti ini:
public void method() { Object o = new Object(); System.out.println(o); }
Ini juga dikenali sebagai Penghapusan Kunci.
Dalam mesin maya Java, memperuntukkan ruang memori untuk objek yang dicipta pada timbunan Java hampir masuk akal kepada pengaturcara Java. selagi anda memegang rujukan kepada objek ini, anda boleh mengakses data objek yang disimpan dalam timbunan. Subsistem pengumpulan sampah mesin maya akan mengitar semula objek yang tidak lagi digunakan dalam timbunan, tetapi tindakan kitar semula, sama ada menanda dan menapis objek kitar semula, atau mengitar semula dan menyusun memori, memerlukan banyak sumber. Walau bagaimanapun, terdapat kes khas Jika analisis melarikan diri mengesahkan bahawa objek tidak akan terlepas daripada benang, ia mungkin dioptimumkan untuk diperuntukkan pada tindanan. Ini menghapuskan keperluan untuk memperuntukkan memori pada timbunan dan menghapuskan keperluan untuk pengumpulan sampah.
Seperti kod berikut:
public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 1000000; i++) { alloc(); } Thread.sleep(100000); } private static void alloc() { User user = new User(); }
Kod ini sangat mudah, ia adalah untuk mencipta gelung 1 juta kali dan menggunakan kaedah alloc() untuk mencipta 1 juta objek Pengguna. Objek Pengguna yang ditakrifkan dalam kaedah alloc() di sini tidak dirujuk oleh kaedah lain, jadi ia memenuhi keperluan untuk peruntukan pada tindanan.
Parameter JVM adalah seperti berikut:
-Xmx2G -Xms2G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
Mulakan atur cara dan semak bilangan kejadian melalui alat jmap:
jmap -histo pid num #instances #bytes class name ---------------------------------------------- 1: 3771 2198552 [B 2: 10617 1722664 [C 3: 104057 1664912 com.miracle.current.lock.StackAllocationTest$User
Kita dapat melihat bahawa atur cara telah mencipta sejumlah 104057 objek Pengguna, yang jauh kurang daripada 1 juta. Kami boleh mematikan analisis melarikan diri dan melihat sekali lagi:
-Xmx2G -Xms2G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
Mulakan program dan semak bilangan kejadian melalui alat jmap:
jmap -histo 42928 num #instances #bytes class name ---------------------------------------------- 1: 628 22299176 [I 2: 1000000 16000000 com.miracle.current.lock.StackAllocationTest$User
Anda dapat melihat bahawa sejumlah 1 juta objek Pengguna telah dicipta selepas mematikan analisis melarikan diri . Sebagai perbandingan, peruntukan pada tindanan memainkan peranan penting dalam penggunaan memori timbunan dan GC.
Jika data tidak lagi boleh diuraikan menjadi data yang lebih kecil untuk diwakili, jenis data asal dalam mesin maya Java (int, long dan jenis berangka lain dan jenis rujukan, dsb.) tidak boleh digunakan Selanjutnya Terurai, maka data ini boleh dipanggil skalar. Sebaliknya, jika sekeping data boleh terus diuraikan, ia dipanggil agregat dalam Java ialah agregat biasa.
Jika analisis melarikan diri boleh membuktikan bahawa objek tidak akan diakses di luar kaedah, dan objek ini boleh dibongkar, maka program mungkin tidak mencipta objek ini apabila ia benar-benar dilaksanakan, sebaliknya mencipta secara langsung beberapa daripadanya untuk digunakan oleh kaedah ini sebaliknya.
mempunyai kod berikut:
public static void main(String[] args) { method(); } private static void method() { User user = new User(25); System.out.println(user.age); } private static class User { private int age; public User(int age) { this.age = age; } }
在method()
方法中创建User对象,指定age为25,这里User不会被其他方法引用,也就是说它不会逃逸出方法,并且User是可以拆解为标量的。所以alloc()
代码会优化为如下:
private static void alloc() { int age = 25; System.out.println(age); }
尽管目前逃逸分析技术仍在发展之中,未完全成熟,但它是即时编译器优化技术的一个重要前进方向,在日后的Java虚拟机中,逃逸分析技术肯定会支撑起一系列更实用、有效的优化技术。
Atas ialah kandungan terperinci Fahami analisis pelarian JVM dalam masa 3 minit. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!