GC处理可预测和保留的资源。VM对其具有完全控制权,并完全控制创建哪些实例以及何时创建实例。此处的关键字为“保留”和“完全控制”。句柄是由OS分配的,而指针则是指向在托管空间之外分配的资源的指针。因此,句柄和指针不限于在托管代码中使用。它们可以(并且经常)由在同一进程上运行的托管和非托管代码使用。
“资源收集器”将能够验证是否在托管空间内使用了句柄/指针,但是根据定义,它不知道其内存空间之外发生了什么(而且,更糟糕的是,可以使用某些句柄)跨过程边界)。
一个实际的例子是.NET CLR。可以使用调味的C ++编写可同时用于托管和非托管内存空间的代码。句柄,指针和引用可以在托管和非托管代码之间传递。非托管代码必须使用特殊的构造/类型,以允许CLR跟踪对其托管资源的引用。但这是最好的。它不能对句柄和指针做同样的事情,因此,资源收集器将不知道是否可以释放特定的句柄或指针。
编辑:关于.NET CLR,我对使用.NET平台进行C ++开发没有经验。也许有一些特殊的机制可以使CLR跟踪对托管和非托管代码之间的句柄/指针的引用。如果是这种情况,那么CLR可以照顾这些资源的生命周期,并在所有对它们的引用都被清除时释放它们(嗯,至少在某些情况下可以)。无论哪种方式,最佳实践都要求在不需要它们时应立即释放句柄(尤其是指向文件的句柄)和指针。资源收集器将不遵守该要求,这是另一个原因。
编辑2:在CLR / JVM / VMs-general上,如果仅在托管空间内使用某些代码来释放特定的句柄,则相对来说比较琐碎。在.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);