GC berkaitan dengan sumber daya yang dapat diprediksi dan dicadangkan . VM memiliki kontrol total terhadapnya dan memiliki kontrol total atas instance apa yang dibuat dan kapan. Kata kunci di sini adalah "milik" dan "kontrol total". Pegangan dialokasikan oleh OS, dan pointer ... pointer juga ke sumber daya yang dialokasikan di luar ruang yang dikelola. Karena itu, pegangan dan pointer tidak terbatas untuk digunakan di dalam kode yang dikelola. Mereka dapat digunakan - dan seringkali - dengan kode yang dikelola dan tidak dikelola yang berjalan pada proses yang sama.
"Resource Collector" akan dapat memverifikasi apakah pegangan / penunjuk sedang digunakan dalam ruang yang dikelola atau tidak, tetapi menurut definisi tidak mengetahui apa yang terjadi di luar ruang memori itu (dan, untuk membuat keadaan lebih buruk beberapa pegangan dapat digunakan melintasi batas proses).
Contoh praktis adalah .NET CLR. Seseorang dapat menggunakan C ++ yang diberi aroma untuk menulis kode yang bekerja dengan ruang memori yang dikelola dan tidak dikelola; pegangan, penunjuk dan referensi dapat diedarkan antara kode yang dikelola dan tidak dikelola. Kode yang tidak dikelola harus menggunakan konstruksi / tipe khusus untuk memungkinkan CLR untuk terus melacak referensi yang dibuat untuk sumber daya yang dikelola itu. Tapi itu yang terbaik yang bisa dilakukan. Ia tidak dapat melakukan hal yang sama dengan handle dan pointer, dan karena itu Resource Collector tidak akan tahu apakah boleh melepaskan handel atau pointer tertentu.
sunting: Mengenai. NET CLR, saya tidak berpengalaman dengan pengembangan C ++ dengan platform .NET. Mungkin ada mekanisme khusus di tempat yang memungkinkan CLR untuk terus melacak referensi untuk menangani / petunjuk antara kode yang dikelola dan tidak dikelola. Jika itu yang terjadi maka CLR dapat mengurus masa pakai sumber daya tersebut dan melepaskannya ketika semua referensi tentangnya telah dihapus (yah, setidaknya dalam beberapa skenario hal itu bisa). Either way, praktik terbaik menentukan yang menangani (terutama yang menunjuk ke file) dan pointer harus dirilis segera setelah mereka tidak diperlukan. Seorang Resource Collector tidak akan menaatinya, itu alasan lain untuk tidak memilikinya.
sunting 2: Ini relatif sepele pada CLR / JVM / VMs-in-general untuk menulis beberapa kode untuk membebaskan pegangan tertentu jika hanya digunakan di dalam ruang yang dikelola. Dalam. NET akan menjadi sesuatu seperti:
// This class offends many best practices, but it would do the job.
public class AutoReleaseFileHandle {
// keeps track of how many instances of this class is in memory
private static int _toBeReleased = 0;
// the threshold when a garbage collection should be forced
private const int MAX_FILES = 100;
public AutoReleaseFileHandle(FileStream fileStream) {
// Force garbage collection if max files are reached.
if (_toBeReleased >= MAX_FILES) {
GC.Collect();
}
// increment counter
Interlocked.Increment(ref _toBeReleased);
FileStream = fileStream;
}
public FileStream { get; private set; }
private void ReleaseFileStream(FileStream fs) {
// decrement counter
Interlocked.Decrement(ref _toBeReleased);
FileStream.Close();
FileStream.Dispose();
FileStream = null;
}
// Close and Dispose the Stream when this class is collected by the GC.
~AutoReleaseFileHandle() {
ReleaseFileStream(FileStream);
}
// because it's .NET this class should also implement IDisposable
// to allow the user to dispose the resources imperatively if s/he wants
// to.
private bool _disposed = false;
public void Dispose() {
if (_disposed) {
return;
}
_disposed = true;
// tells GC to not call the finalizer for this instance.
GC.SupressFinalizer(this);
ReleaseFileStream(FileStream);
}
}
// use it
// for it to work, fs.Dispose() should not be called directly,
var fs = File.Open("path/to/file");
var autoRelease = new AutoReleaseFileHandle(fs);