Bagaimana cara memaksa pengumpulan sampah di Jawa?

225

Apakah mungkin untuk memaksa pengumpulan sampah di Jawa, bahkan jika itu sulit dilakukan? Saya tahu System.gc();dan Runtime.gc();tetapi mereka hanya menyarankan untuk melakukan GC. Bagaimana saya bisa memaksakan GC?

Robert Columbia
sumber
30
Mungkin akan bermanfaat untuk memberikan latar belakang mengapa Anda perlu memaksakan GC. Biasanya dalam bahasa sampah yang dikumpulkan itu adalah praktik yang buruk untuk secara eksplisit memanggil kolektor.
Justin Ethier
3
JVM yang diberikan dapat memberikan beberapa metode pengumpulan sampah, masing-masing dengan kelebihan dan kekurangannya sendiri, dan seringkali situasi tertentu dapat dihindari hanya dengan mengisyaratkan JVM pada waktu startup. Harap uraikan skenario.
Thorbjørn Ravn Andersen
3
jmap -histo: live <pid> stackoverflow.com/questions/6418089/…
5
Berikut ini adalah use case untuk memaksa pengumpulan sampah: Saya memiliki server dengan tumpukan 30GB, yang ~ 12GB biasanya digunakan (~ objek 5M). Setiap 5 menit, server menghabiskan kira-kira satu menit untuk melakukan tugas kompleks di mana sekitar 35 juta objek tambahan digunakan. GC penuh dipicu beberapa kali per jam, selalu selama tugas kompleks, dan membekukan VM selama 10 hingga 15 detik. Saya ingin memaksa GC penuh untuk berjalan pada saat tugas yang rumit tidak berjalan; itu akan menjadi juggling objek hidup 5M daripada 40M.
Steve
3
@JustinEthier Ada satu kasus yang cukup jelas di mana Anda mungkin ingin memaksakan GC, yaitu unit yang menguji perilaku apa pun yang melibatkan hirarki tipe java.lang.ref.Reference.
Elias Vasylenko

Jawaban:

168

Pilihan terbaik Anda adalah menelepon System.gc()yang hanya merupakan petunjuk bagi pengumpul sampah yang Anda inginkan untuk melakukan pengumpulan. Tidak ada cara untuk memaksa dan mengumpulkan segera karena pemulung tidak menentukan.

Andrew Hare
sumber
28
Seharusnya ada. non-deterministic == trouble
Pacerier
7
Seorang pengumpul sampah mungkin tidak deterministik dan masih menawarkan cara untuk memaksa pengumpulan langsung. Misalnya, biasanya .NET collector adalah non-deterministik tetapi panggilan ke GC.Collect () memaksanya berjalan. Hanya saja Java memilih untuk tidak mengekspos fungsi ini.
Petr Hudeček
2
Dalam pengalaman saya, metode ini selalu memanggil pengumpul sampah. Ia melakukannya dengan cukup teratur sehingga plot penggunaan memori saya versus jumlah objek yang dideklarasikan selalu benar-benar linier (akuntansi untuk padding, dll.).
Jim Pivarski
Saya berpikir bahwa dengan mengalokasikan objek-objek baru dan kemudian tidak mereferensikannya lagi, pengumpul sampah secara otomatis akan berjalan
Bionix1441
@ PetrHudeček Dalam aplikasi dunia nyata .NET GC.Collect()tidak mengumpulkan. Di Jawa gc()tidak.
ajeh
53

The jlibs perpustakaan memiliki kelas utilitas yang baik untuk pengumpulan sampah . Anda dapat memaksa pengumpulan sampah menggunakan sedikit trik bagus dengan objek WeakReference .

RuntimeUtil.gc () dari jlibs:

   /**
    * This method guarantees that garbage collection is
    * done unlike <code>{@link System#gc()}</code>
    */
   public static void gc() {
     Object obj = new Object();
     WeakReference ref = new WeakReference<Object>(obj);
     obj = null;
     while(ref.get() != null) {
       System.gc();
     }
   }
Syams
sumber
1
Kode ini rusak karena referensi lemah akan dihapus segera setelah referensi menjadi lemah dijangkau, yang sebelum dihapus dari memori.
Marko Topolnik
1
Anda mungkin mengacaukan arti "GC telah berjalan" dengan "memori telah direklamasi". Objek hidup dan bahkan belum selesai, tetapi Anda tidak dapat mengaksesnya lagi melalui referensi yang lemah. Cara yang agak lebih baik adalah menggunakan a PhantomReferencedengan ReferenceQueuedan kemudian Anda akan diberi tahu setelah finalisasi, tetapi masih sebelum pembersihan. Akhirnya, bahkan jika Anda berhasil mendeteksi bahwa memori untuk objek ini direklamasi, itu masih berarti sangat sedikit dalam GC generasi seperti HotSpot. Biasanya itu akan bertepatan dengan pembersihan generasi muda.
Marko Topolnik
20
OP meminta, dan Anda mengklaim memberikan, solusi untuk "memaksa pengumpulan sampah". Menjalankan subsistem GC adalah satu hal, sebenarnya mengumpulkan sampah adalah hal lain. Sampel kode yang Anda berikan jelas maksud untuk menjamin sampah telah dikumpulkan. Bagaimanapun, ini menjadi pertanyaan yang sangat lama, ini jelas bukan tentang keinginan OP, tetapi utilitas untuk masyarakat umum. Tidak ada yang tertarik "memaksa subsistem GC untuk menjalankan" sendiri, tanpa sampah dikumpulkan. Bahkan, orang biasanya menginginkan jaminan bahwa semua sampah sudah terkumpul.
Marko Topolnik
4
Anda mungkin tidak membandingkannya dengan efisiensi System.gc(); System.gc();, tetapi tentu akan menarik untuk mengetahui apakah itu pernah bekerja lebih baik dari itu. Bahkan, hanya mencetak berapa kali disebut System.gc()sudah cukup. Peluang untuk mencapai 2 cukup tipis.
Marko Topolnik
3
@MarkoTopolnik: 'Tidak ada yang tertarik pada "memaksa subsistem GC untuk berjalan" sendiri, tanpa sampah dikumpulkan' .... Sebenarnya saya hanya tertarik dengan perilaku ini hari ini. Saya bersyukur jawaban ini hadir. Tujuan saya adalah memeriksa perilaku rotasi penanganan log GC, dan mendapatkan format output GC. Trik kecil ini membantu saya mengisi log GC dengan cepat.
erik.weathers
49

Cara terbaik (jika tidak hanya) untuk memaksa GC adalah dengan menulis JVM khusus. Saya percaya para pengumpul Sampah bisa dicolokkan sehingga Anda mungkin bisa memilih salah satu implementasi yang tersedia dan mengubahnya.

Catatan: Ini BUKAN jawaban yang mudah.

Mainguy
sumber
40
+1 untuk lulz. tidak ada yang membuat debugging frustasi lebih baik daripada seseorang dengan selera humor. selain jawaban yang benar-benar bisa digunakan, yaitu.
jsh
25

YA hampir mungkin memaksa Anda harus memanggil metode dengan urutan yang sama dan pada saat yang sama ini adalah:

System.gc ();
System.runFinalization ();

bahkan jika hanya satu objek untuk membersihkan penggunaan kedua metode ini pada saat yang sama memaksa pemulung untuk menggunakan finalise()metode objek yang tidak terjangkau membebaskan memori yang ditugaskan dan melakukan apa yang finalize()dinyatakan oleh metode.

NAMUN merupakan praktik yang mengerikan untuk menggunakan pengumpul sampah karena penggunaannya dapat memperkenalkan kelebihan beban ke perangkat lunak yang mungkin bahkan lebih buruk daripada pada memori, pengumpul sampah memiliki utas sendiri yang tidak mungkin untuk dikontrol plus tergantung pada algoritma yang digunakan oleh gc bisa memakan waktu lebih lama dan dianggap sangat tidak efisien, Anda harus memeriksa perangkat lunak Anda jika terburuk dengan bantuan gc karena sudah pasti rusak, solusi yang baik tidak boleh bergantung pada gc.

CATATAN: hanya untuk diingat ini hanya akan berfungsi jika dalam metode finalisasi bukan penugasan kembali objek, jika ini terjadi objek akan tetap hidup dan akan memiliki kebangkitan yang secara teknis memungkinkan.

legramira
sumber
10
TIDAK , bahkan kedua perintah ini TIDAK akan memaksa pengumpulan sampah. Seperti yang sudah disebutkan oleh orang lain, gc()hanya isyarat untuk menjalankan pengumpulan sampah. runFinalizers()hanya menjalankan finalizer pada objek "yang telah ditemukan dibuang". Jika gc tidak benar-benar berjalan, mungkin tidak ada objek seperti itu ...
Steffen Heil
juga, System.runFinalization () bukan jaminan bahwa apa pun akan berjalan; mungkin saja tidak ada yang terjadi sama sekali. Ini adalah saran - dari Javadoc: " Memanggil metode ini menunjukkan bahwa Java Virtual Machine mengeluarkan upaya untuk menjalankan metode finalisasi objek yang telah ditemukan dibuang tetapi metode finalisasinya belum dijalankan "
kaan
21

Di bawah dokumentasi untuk OutOfMemoryError ia menyatakan bahwa itu tidak akan dibuang kecuali VM telah gagal untuk mendapatkan kembali memori setelah pengumpulan sampah penuh. Jadi, jika Anda terus mengalokasikan memori hingga Anda mendapatkan kesalahan, Anda sudah akan terpaksa mengumpulkan sampah penuh.

Mungkin pertanyaan yang benar-benar ingin Anda tanyakan adalah "bagaimana saya bisa mendapatkan kembali memori yang saya pikir saya harus reklamasi dengan pengumpulan sampah?"

Pete Kirkham
sumber
18

Untuk Meminta GC secara manual (bukan dari System.gc ()):

  1. Pergi Ke: folder bin di JDK misalnya.-C: \ Program Files \ Java \ jdk1.6.0_31 \ bin
  2. Buka jconsole.exe
  3. Hubungkan ke Proses lokal yang diinginkan.
  4. Buka Ke memori tab dan klik melakukan GC.
Pinkesh Sharma
sumber
3
Oppss menyesatkan. Tolong arahkan mouse ke tombol "Lakukan GC". Anda dapat meminta JVM untuk melakukan GC tetapi tidak pernah memaksa.
Kumaran
@InkinkSharma, Ini tidak berlaku . Itu hanya permintaan yang mungkin bisa diabaikan sepenuhnya.
Pacerier
@Pacerier Di dunia yang ideal ya .. tetapi jika Anda melakukan ini, Anda akan melihat bahwa ada peningkatan memori secara instan ...
Pinkesh Sharma
11

.gc adalah kandidat untuk eliminasi dalam rilis mendatang - Insinyur Sun pernah berkomentar bahwa mungkin kurang dari dua puluh orang di dunia yang benar-benar tahu cara menggunakan .gc () - Saya melakukan pekerjaan tadi malam selama beberapa jam di pusat / kritis struktur data menggunakan data yang dihasilkan SecureRandom, di suatu tempat hanya melewati 40.000 objek vm akan melambat seolah-olah kehabisan pointer. Jelas itu tersedak tabel pointer 16-bit dan menunjukkan perilaku "mesin gagal" klasik.

Saya mencoba -Xms dan seterusnya, terus sedikit memutar-mutar sampai berjalan sekitar 57, xxx sesuatu. Maka itu akan menjalankan gc dari mengatakan 57.127 menjadi 57.128 setelah gc () - sekitar kecepatan code-bloat di camp Easy Money.

Desain Anda perlu dikerjakan ulang secara mendasar, mungkin pendekatan jendela geser.

Nicholas Jordan
sumber
1
Saya memiliki sesuatu seperti itu, banyak objek dalam memori yang tidak dapat saya alokasinya. Pengecualian OutOfMemory dilemparkan, saya ingin Force GC untuk menguji apakah ada beberapa proses pembuatan Objek Infinite atau objek ini adalah yang digunakan oleh sistem saya.
Kedengarannya seperti Anda sedang mengerjakan masalah yang sama saya, tolong jelaskan: "Penciptaan Objek Tak Terbatas" ... proyek penelitian yang baik, mungkin Anda dapat memposting pertanyaan atau sesuatu di area java di sini (saya mengurutkan baru di sini dan tidak tahu "Finite Automa" tentang cara kerja situs) Saya mencoba kemarin dan akhirnya melakukan file.dat ketika kompiler mengeluh "terlalu banyak kode" pada 40.000 base36 BigIntegers dikodekan sebagai String akhir statis [] Saya akan tetap di leher saya di sini dan berspekulasi bahwa seluruh JVM terbatas pada 16-bit pointer, saya yakin apa yang harus kita lakukan adalah nol agresif dan membaca dari disk ...
Nicholas Jordan
Sungguh, saya tidak mengerti Anda. Tetapi untuk memperjelas "Penciptaan Objek Tak Terbatas" yang saya maksudkan adalah ada beberapa kode di sistem besar saya yang membuat objek yang menangani dan hidup dalam memori, saya tidak bisa mendapatkan kode ini sebenarnya, hanya isyarat !!
5
Omong kosong! Ada satu kasus yang jelas di mana itu harus digunakan: menguji kode yang menggunakan referensi lemah, sehingga kita dapat memastikan bahwa perilaku sudah benar ketika referensi yang lemah dibersihkan.
Elias Vasylenko
6

Spesifikasi JVM tidak mengatakan sesuatu yang spesifik tentang pengumpulan sampah. Karena itu, vendor bebas menerapkan GC dengan cara mereka.

Jadi ketidakjelasan ini menyebabkan ketidakpastian dalam perilaku pengumpulan sampah. Anda harus memeriksa detail JVM Anda untuk mengetahui tentang pendekatan / algoritma pengumpulan sampah. Juga ada opsi untuk menyesuaikan perilaku.

rai.skumar
sumber
4

Jika Anda perlu memaksakan pengumpulan sampah, mungkin Anda harus mempertimbangkan bagaimana Anda mengelola sumber daya. Apakah Anda membuat objek besar yang bertahan dalam memori? Apakah Anda membuat objek besar (misalnya, kelas grafis) yang memiliki Disposableantarmuka dan tidak memanggil dispose()ketika selesai dengannya? Apakah Anda mendeklarasikan sesuatu di tingkat kelas yang hanya Anda perlukan dalam satu metode?

Bob Kaufman
sumber
2

Akan lebih baik jika Anda menjelaskan alasan mengapa Anda membutuhkan pengumpulan sampah. Jika Anda menggunakan SWT, Anda dapat membuang sumber daya seperti Imagedan Fontuntuk membebaskan memori. Misalnya:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

Ada juga alat untuk menentukan sumber daya yang tidak diinginkan.

Paul Lammertsma
sumber
bagaimana jika tidak ada metode buang?
ArifMustafa
1
Sama sekali tidak berhubungan dengan pertanyaan! Tidak, saya tidak menggunakan SWT. Saya memanggil metode JNI yang membuka jendela .NET melalui lapisan asli Delphi. Saya juga memiliki inti perhitungan FORTRAN yang menerima data melalui lapisan C ++ asli. Apa hubungannya itu dengan apa pun? Bisakah saya memaksakan GC atau tidak? Tidak? :-(
Mostafa Zeinali
0

Jika Anda kehabisan memori dan mendapatkan yang OutOfMemoryExceptionAnda dapat mencoba meningkatkan jumlah ruang tumpukan yang tersedia untuk java dengan memulai program Anda dengan java -Xms128m -Xmx512mbukan hanya java. Ini akan memberi Anda ukuran tumpukan awal 128Mb dan maksimum 512Mb, yang jauh lebih dari standar 32Mb / 128Mb.

Viktor Dahl
sumber
Pengaturan memori default adalahjava -Xms512M -Xmx1024M
ThePyroEagle
0

Pilihan lain adalah tidak membuat objek baru.

Penyatuan objek jauh untuk mengurangi kebutuhan GC di Jawa.

Pengumpulan objek umumnya tidak akan lebih cepat dari Pembuatan objek (terutama untuk objek ringan) tetapi lebih cepat dari Pengumpulan Sampah. Jika Anda membuat 10.000 objek dan setiap objek adalah 16 byte. 160.000 byte GC harus diperoleh kembali. Di sisi lain, jika Anda tidak membutuhkan semua 10.000 pada saat yang sama, Anda dapat membuat kumpulan untuk mendaur ulang / menggunakan kembali objek yang menghilangkan kebutuhan untuk membangun objek baru dan menghilangkan kebutuhan untuk GC objek lama.

Sesuatu seperti ini (belum diuji). Dan jika Anda menginginkannya aman, Anda dapat menukar keluar LinkedList dengan ConcurrentLinkedQueue.

public abstract class Pool<T> {
    private int mApproximateSize;
    private LinkedList<T> mPool = new LinkedList<>();

    public Pool(int approximateSize) {
        mApproximateSize = approximateSize;
    }

    public T attain() {
        T item = mPool.poll();
        if (item == null) {
            item = newInstance();
        }
        return item;
    }

    public void release(T item) {
        int approxSize = mPool.size(); // not guaranteed accurate
        if (approxSize < mApproximateSize) {
            recycle(item);
            mPool.add(item);
        } else if (approxSize > mApproximateSize) {
            decommission(mPool.poll());
        }
    }

    public abstract T newInstance();

    public abstract void recycle(T item);

    public void decommission(T item) { }

}
Aaron T Harris
sumber
0

Pada OracleJDK 10 dengan G1 GC, satu panggilan ke System.gc()akan menyebabkan GC membersihkan Koleksi Lama. Saya tidak yakin apakah GC langsung berjalan. Namun, GC tidak akan membersihkan Young Collection bahkan jika System.gc()dipanggil berkali-kali dalam satu lingkaran. Untuk mendapatkan GC untuk membersihkan Koleksi Muda, Anda harus mengalokasikan dalam satu lingkaran (mis. new byte[1024]) Tanpa menelepon System.gc(). Menelepon System.gc()untuk beberapa alasan mencegah GC dari membersihkan Young Collection.

Nathan
sumber
0

Sungguh, saya tidak mengerti Anda. Tetapi untuk memperjelas "Penciptaan Objek Tak Terbatas" yang saya maksudkan adalah ada beberapa kode di sistem besar saya yang membuat objek yang menangani dan hidup dalam memori, saya tidak bisa mendapatkan kode ini sebenarnya, hanya isyarat !!

Ini benar, hanya isyarat. Anda memiliki cukup banyak jawaban standar yang sudah diberikan oleh beberapa poster. Mari kita ambil satu per satu ini:

  1. Sebenarnya saya tidak bisa mendapatkan kode ini

Benar, tidak ada jvm yang sebenarnya - hanya ada spesifikasi, sekelompok ilmu komputer yang menggambarkan perilaku yang diinginkan ... Saya baru saja menggali untuk menginisialisasi objek Java dari kode asli. Untuk mendapatkan apa yang Anda inginkan, satu-satunya cara adalah melakukan apa yang disebut agresif nulling. Kesalahan jika dilakukan salah begitu buruk sehingga kita harus membatasi diri pada lingkup asli dari pertanyaan:

  1. beberapa kode di sistem besar saya melakukan penciptaan objek

Sebagian besar poster di sini akan menganggap Anda mengatakan Anda bekerja pada sebuah antarmuka, jika demikian kami harus melihat apakah Anda sedang menyerahkan seluruh objek atau satu item pada suatu waktu.

Jika Anda tidak lagi membutuhkan objek, Anda dapat menetapkan null ke objek tetapi jika Anda salah ada pengecualian null pointer yang dihasilkan. Saya yakin Anda dapat mencapai pekerjaan yang lebih baik jika Anda menggunakan NIO

Setiap kali Anda atau saya atau orang lain mendapatkan: " Tolong saya sangat membutuhkannya. " Ini hampir merupakan prekursor universal untuk kehancuran total yang hampir sama dengan apa yang Anda coba kerjakan .... tulis kami kode sampel kecil, bersihkan dari apa pun kode aktual yang digunakan dan tunjukkan pertanyaan Anda kepada kami.

Jangan frustrasi. Seringkali apa yang dipecahkan adalah dBA Anda menggunakan paket yang dibeli di suatu tempat dan desain aslinya tidak diubah untuk struktur data yang besar.

Itu sangat umum.

Nicholas Jordan
sumber
-1

FYI

Pemanggilan metode System.runFinalizersOnExit (true) menjamin bahwa metode finalizer dipanggil sebelum Java dimatikan. Namun, metode ini secara inheren tidak aman dan telah usang. Alternatifnya adalah menambahkan "shutdown hooks" dengan metode Runtime.addShutdownHook.

Masarrat Siddiqui

Masarrat Siddiqui
sumber
Kelemahan dengan kait shutdown adalah bahwa mereka jarang benar-benar berfungsi. Pengakhiran paksa tidak berfungsi, kode keluar bukan-nol tidak bekerja, dan kadang-kadang JVM (resmi) tidak menjalankannya selama Anda membutuhkannya untuk dijalankan.
ThePyroEagle
-1

Ada beberapa cara tidak langsung untuk memaksa pemulung. Anda hanya perlu mengisi tumpukan dengan benda-benda sementara sampai titik ketika pengumpul sampah akan mengeksekusi. Saya telah membuat kelas yang memaksa pemulung dengan cara ini:

class GarbageCollectorManager {

    private static boolean collectionWasForced;
    private static int refCounter = 0;

    public GarbageCollectorManager() {
        refCounter++;
    }

    @Override
    protected void finalize() {
        try {
            collectionWasForced = true;
            refCounter--;
            super.finalize();   
        } catch (Throwable ex) {
            Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int forceGarbageCollection() {
        final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
        int iterationsUntilCollected = 0;
        collectionWasForced = false;

        if (refCounter < 2) 
            new GarbageCollectorManager();

        while (!collectionWasForced) {
            iterationsUntilCollected++;
            int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
            arr = null;
        }

        return iterationsUntilCollected;
    }

}

Pemakaian:

GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();

Saya tidak tahu berapa banyak metode ini berguna, karena mengisi tumpukan terus-menerus, tetapi jika Anda memiliki aplikasi misi kritis yang HARUS memaksa GC - saat ini mungkin cara portabel Java untuk memaksa GC.

Agnius Vasiliauskas
sumber
Apa itu "final TEM TEMARYARY_ARRAY_SIZE_FOR_GC = 200_000;"?
Koray Tugay
Ukuran array - berapa banyak objek sementara (int) yang akan dihasilkan agar GC mulai bekerja.
Agnius Vasiliauskas
Apakah ini valid: "_" dalam bilangan bulat?
Koray Tugay
1
Ya, garis bawah dalam literal angka valid mulai dari Java SE 7. Ini berguna misalnya sebagai pemisah ribuan dalam integer seperti dalam kasus ini.
Agnius Vasiliauskas
3
Anda tidak boleh menjalankan kode seperti itu dalam sistem produksi. Sementara kode ini berjalan dalam satu utas, utas lainnya juga dapat memperoleh OutOfMemoryException, sepenuhnya membalikkan niat untuk memanggil ini di tempat pertama ....
Steffen Heil
-1

Saya ingin menambahkan sesuatu di sini. Tolong bukan bahwa Java berjalan pada Mesin Virtual dan bukan Mesin yang sebenarnya. Mesin virtual memiliki cara komunikasi sendiri dengan mesin. Ini mungkin bervariasi dari satu sistem ke sistem lainnya. Sekarang Ketika kita memanggil GC kita meminta Mesin Virtual Java untuk memanggil Pengumpul Sampah.

Karena Pengumpul Sampah menggunakan Mesin Virtual, kami tidak dapat memaksanya melakukan pembersihan di sana dan kemudian. Sebaliknya, kami mengantri permintaan kami dengan Pengumpul Sampah. Itu tergantung pada Mesin Virtual, setelah waktu tertentu (ini dapat berubah dari sistem ke sistem, umumnya ketika ambang memori yang dialokasikan untuk JVM penuh) mesin yang sebenarnya akan membebaskan ruang. : D

Saubhagya Ranjan Das
sumber
Kalimat pertama paragraf kedua adalah non sequitur .
Marquis of Lorne
-1

Kode berikut diambil dari metode assertGC (...). Ini mencoba untuk memaksa pengumpul sampah nondeterministic untuk mengumpulkan.

   List<byte[]> alloc = new ArrayList<byte[]>();
   int size = 100000;
   for (int i = 0; i < 50; i++) {
        if (ref.get() == null) {
             // Test succeeded! Week referenced object has been cleared by gc.
             return;
        }
        try {
             System.gc();
        } catch (OutOfMemoryError error) {
             // OK
        }
        try {
             System.runFinalization();
        } catch (OutOfMemoryError error) {
             // OK
        }

        // Approach the jvm maximal allocatable memory threshold
        try {
             // Allocates memory.
             alloc.add(new byte[size]);

             // The amount of allocated memory is increased for the next iteration.
             size = (int)(((double)size) * 1.3);
        } catch (OutOfMemoryError error) {
             // The amount of allocated memory is decreased for the next iteration.
             size = size / 2;
        }

        try {
             if (i % 3 == 0) Thread.sleep(321);
        } catch (InterruptedException t) {
             // ignore
        }
   }

   // Test failed! 

   // Free resources required for testing
   alloc = null;

   // Try to find out who holds the reference.
   String str = null;
   try {
        str = findRefsFromRoot(ref.get(), rootsHint);
   } catch (Exception e) {
        throw new AssertionFailedErrorException(e);
   } catch (OutOfMemoryError err) {
        // OK
   }
   fail(text + ":\n" + str);

Sumber (saya menambahkan beberapa komentar untuk kejelasan): Contoh NbTestCase

H. Hess
sumber
-1

Anda dapat mencoba menggunakan Runtime.getRuntime().gc()atau menggunakan metode utilitas System.gc()Catatan: Metode ini tidak memastikan GC. Dan ruang lingkup mereka harus dibatasi pada JVM daripada secara terprogram menangani aplikasi Anda.

nabster
sumber
2
Seperti dijelaskan dalam jawaban lain, metode-metode itu tidak memaksa menjalankan pengumpulan sampah (lengkap).
Aliran
-2

Jika Anda menggunakan JUnit dan Spring, coba tambahkan ini di setiap kelas tes:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
Aliuk
sumber