System.gc()調用 - 適用的場景
一、System.gc()調用
System.gc()用於調用垃圾收集器,在調用時,垃圾收集器將運行以回收未使用的內存空間。它將嘗試釋放被丟棄對象占用的內存。然而System.gc()調用附帶一個免責聲明,無法保證對垃圾收集器的調用。我們習慣了從現實世界的經驗中獲得的“條件適用”。一切都附有免責聲明!
JVM實現者可以通過System.gc()調用來決定JVM的行為。一般來說,我們在編寫Java代碼並將其留給JVM時,不要考慮內存管理。在一些特殊情況下,如我們正在編寫一個性能基準,我們可以在運行之間調用System.gc()。以下是調用gc有所作為的另一個例子。
二、MappedByteBuffer與System.gc()
MappedByteBuffer用於需要最佳IO性能的地方。MappedByteBuffer提供到底層文件的直接內存映射。
API Javadoc說,
內存映射文件的許多細節固有地依賴於底層操作系統,因此是未指定的。當請求的區域未完全包含在該通道的文件中時,此方法的行為是未指定的。對該程序或另一個的底層文件的內容或大小進行的更改是否被傳播到緩沖區是未指定的。沒有指定將緩沖區的更改傳播到文件的速率。
幾乎所有的東西都是未指定的,並留給底層操作系統。我們來看下面的代碼:
package com.javapapers.java; import java.io.File; import java.io.IOException;import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class MappedFileGc { public static void main(String[] args) throws IOException { File tempFile = File.createTempFile("Temp", null); tempFile.deleteOnExit(); RandomAccessFile raTempFile= new RandomAccessFile(tempFile, "rw"); FileChannel fChannel = raTempFile.getChannel(); MappedByteBuffer mappedBuffer = fChannel.map( FileChannel.MapMode.READ_WRITE, 0, 512); fChannel.close(); raTempFile.close(); mappedBuffer = null; System.gc(); if (tempFile.delete()) System.out.println("Successfully deleted: " + tempFile); else System.out.println("Unable to delete: " + tempFile); } }
在上面的代碼中,行號24 System.gc()被註釋。當我現在運行這個程序,總是得到“ Unable to delete: … ”。現在可以取消註釋System.gc()並重新運行它多次以了解行為。現在我們得到“Successfully deleted: …”。大部分時間,我測試的與ByteBuffer相同,垃圾收集立即發生。
相似的,因為MappedByteBuffer依賴於操作系統,垃圾收集器不能立即回收。但是當我們調用System.gc()垃圾收集器釋放句柄,我們可以刪除該文件。推薦一下,“在使用MappedByteBuffer的同時,如果我們正在使用內存敏感程序,那麽最好調用System.gc()”。請註意,此行為依賴於JVM。
System.gc()調用 - 適用的場景