GC имеет дело с предсказуемым и зарезервированным ресурсом. ВМ имеет полный контроль над ней и полный контроль над тем, какие экземпляры создаются и когда. Ключевыми словами здесь являются «зарезервированный» и «тотальный контроль». Дескрипторы выделяются ОС, а указатели являются ... хорошо указателями на ресурсы, выделенные за пределами управляемого пространства. Из - за этого, ручка и указатели не ограничены для использования внутри управляемого кода. Они могут использоваться - и часто - управляемым и неуправляемым кодом, выполняющимся в одном и том же процессе.
«Сборщик ресурсов» сможет проверить, используется ли указатель / указатель в управляемом пространстве или нет, но он по определению не знает, что происходит за пределами его пространства памяти (и, что еще хуже, могут использоваться некоторые дескрипторы через границы процесса).
Практическим примером является .NET CLR. Можно использовать ароматизированный C ++ для написания кода, который работает как с управляемым, так и с неуправляемым пространством памяти; дескрипторы, указатели и ссылки могут передаваться между управляемым и неуправляемым кодом. Неуправляемый код должен использовать специальные конструкции / типы, чтобы позволить CLR отслеживать ссылки на его управляемые ресурсы. Но это лучшее, что может сделать. Он не может сделать то же самое с дескрипторами и указателями, и из-за этого Resource Collector не будет знать, можно ли освободить определенный дескриптор или указатель.
редактирование: Что касается .NET CLR, я не имел опыта разработки C ++ с платформой .NET. Возможно, существуют специальные механизмы, позволяющие CLR отслеживать ссылки на указатели / указатели между управляемым и неуправляемым кодом. Если это так, то CLR может позаботиться о времени жизни этих ресурсов и освободить их, когда все ссылки на них будут очищены (ну, по крайней мере, в некоторых сценариях это может). В любом случае, лучшие практики диктуют, что ручки (особенно те, указывающие на файлы) и указатели должны быть освобождены, как только они не нужны. Ресурс Коллектор бы не соблюдающих требования с тем, что это еще одна причина, чтобы не иметь.
редактировать 2: На CLR / JVM / VM в целом довольно просто написать некоторый код для освобождения определенного дескриптора, если он используется только внутри управляемого пространства. В .NET было бы что-то вроде:
// 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);