diff --git a/zircon/kernel/lib/userboot/userboot.cpp b/zircon/kernel/lib/userboot/userboot.cpp
index f7a421a9eef3106ba6cf55da2f6d063a0c51f470..cd965e93303ea0ba37df407e8eb4f891b6b15d9a 100644
--- a/zircon/kernel/lib/userboot/userboot.cpp
+++ b/zircon/kernel/lib/userboot/userboot.cpp
@@ -147,12 +147,16 @@ static zx_status_t get_job_handle(Handle** ptr) {
 
 static zx_status_t get_resource_handle(Handle** ptr) {
     zx_rights_t rights;
-    fbl::RefPtr<ResourceDispatcher> root;
+    KernelHandle<ResourceDispatcher> root;
     zx_status_t result = ResourceDispatcher::Create(&root, &rights, ZX_RSRC_KIND_ROOT, 0, 0, 0,
                                                     "root");
-    if (result == ZX_OK)
-        *ptr = Handle::Make(fbl::RefPtr<Dispatcher>(root.get()),
-                            rights).release();
+    if (result != ZX_OK)
+        return result;
+
+    HandleOwner handle_owner = Handle::Make(ktl::move(root), rights);
+    if (!handle_owner)
+        return ZX_ERR_NO_MEMORY;
+    *ptr = handle_owner.release();
     return result;
 }
 
diff --git a/zircon/kernel/object/include/object/resource_dispatcher.h b/zircon/kernel/object/include/object/resource_dispatcher.h
index 861ca2f4c561a9c4ea1ed12315b6cd18147eeeb6..44b42206951dcff5a3337a8e5969226e683a06b5 100644
--- a/zircon/kernel/object/include/object/resource_dispatcher.h
+++ b/zircon/kernel/object/include/object/resource_dispatcher.h
@@ -33,10 +33,10 @@ public:
     using ResourceList = fbl::DoublyLinkedList<ResourceDispatcher*>;
     using RefPtr = fbl::RefPtr<ResourceDispatcher>;
 
-    // Creates ResourceDispatcher object representing access rights ta
+    // Creates ResourceDispatcher object representing access rights to a
     // given region of address space from a particular address space allocator, or a root resource
     // granted full access permissions. Only one instance of the root resource is created at boot.
-    static zx_status_t Create(ResourceDispatcher::RefPtr* dispatcher,
+    static zx_status_t Create(KernelHandle<ResourceDispatcher>* handle,
                               zx_rights_t* rights,
                               uint32_t kind,
                               uint64_t base,
diff --git a/zircon/kernel/object/resource_dispatcher.cpp b/zircon/kernel/object/resource_dispatcher.cpp
index 23568b52f1948492cdc1d2f308c4a33c9ec01754..b51a6b6ed9b3d4f06b90b7e015ddcd2b3990ab00 100644
--- a/zircon/kernel/object/resource_dispatcher.cpp
+++ b/zircon/kernel/object/resource_dispatcher.cpp
@@ -36,7 +36,7 @@ ResourceDispatcher::ResourceList ResourceDispatcher::static_resource_list_;
 RegionAllocator::RegionPool::RefPtr ResourceDispatcher::region_pool_;
 const char* kLogTag = "Resources:";
 
-zx_status_t ResourceDispatcher::Create(fbl::RefPtr<ResourceDispatcher>* dispatcher,
+zx_status_t ResourceDispatcher::Create(KernelHandle<ResourceDispatcher>* handle,
                                        zx_rights_t* rights,
                                        uint32_t kind,
                                        uint64_t base,
@@ -113,19 +113,19 @@ zx_status_t ResourceDispatcher::Create(fbl::RefPtr<ResourceDispatcher>* dispatch
     // itself. The constructor will handle adding itself to the shared list if
     // necessary.
     fbl::AllocChecker ac;
-    auto disp = fbl::AdoptRef(new (&ac) ResourceDispatcher(kind, base, size, flags,
-                                                           ktl::move(region_uptr),
-                                                           rallocs, resource_list));
+    KernelHandle new_handle(fbl::AdoptRef(new (&ac) ResourceDispatcher(kind, base, size, flags,
+                                                                       ktl::move(region_uptr),
+                                                                       rallocs, resource_list)));
     if (!ac.check()) {
         return ZX_ERR_NO_MEMORY;
     }
 
     if (name != nullptr) {
-        disp->set_name(name, ZX_MAX_NAME_LEN);
+        new_handle.dispatcher()->set_name(name, ZX_MAX_NAME_LEN);
     }
 
     *rights = default_rights();
-    *dispatcher = ktl::move(disp);
+    *handle = ktl::move(new_handle);
 
     LTRACEF("%s [%u, %#lx, %zu] resource created.\n", kLogTag, kind, base, size);
     return ZX_OK;
diff --git a/zircon/kernel/platform/pc/memory.cpp b/zircon/kernel/platform/pc/memory.cpp
index 19f0e76ccc20fdeb4d990e3bec6fa7de42781c60..eb966e6d1b7a4c6c584294da7c9e4a6dc6f90d31 100644
--- a/zircon/kernel/platform/pc/memory.cpp
+++ b/zircon/kernel/platform/pc/memory.cpp
@@ -22,6 +22,7 @@
 #include <vm/vm.h>
 #include <zircon/types.h>
 #include <zircon/boot/e820.h>
+#include <object/handle.h>
 #include <object/resource_dispatcher.h>
 
 #include "platform_p.h"
@@ -46,7 +47,7 @@ constexpr uint8_t kMaxReservedMmioEntries = 64;
 typedef struct reserved_mmio_space {
     uint64_t base;
     size_t len;
-    ResourceDispatcher::RefPtr dispatcher;
+    KernelHandle<ResourceDispatcher> handle;
 } reserved_mmio_space_t;
 reserved_mmio_space_t reserved_mmio_entries[kMaxReservedMmioEntries];
 static uint8_t reserved_mmio_count = 0;
@@ -451,7 +452,8 @@ static void x86_resource_init_hook(unsigned int rl) {
     for (uint8_t i = 0; i < reserved_mmio_count; i++) {
         zx_rights_t rights;
         auto& entry = reserved_mmio_entries[i];
-        zx_status_t st = ResourceDispatcher::Create(&entry.dispatcher, &rights, ZX_RSRC_KIND_MMIO,
+
+        zx_status_t st = ResourceDispatcher::Create(&entry.handle, &rights, ZX_RSRC_KIND_MMIO,
                                                     entry.base, entry.len, ZX_RSRC_FLAG_EXCLUSIVE,
                                                     "platform_memory");
         if (st == ZX_OK) {
diff --git a/zircon/kernel/syscalls/resource.cpp b/zircon/kernel/syscalls/resource.cpp
index 9c954f56f3e29f6da9f2c329d8acbf44d8c2f3fe..51e29731c9995c0e5053714630b8dc73621c5db3 100644
--- a/zircon/kernel/syscalls/resource.cpp
+++ b/zircon/kernel/syscalls/resource.cpp
@@ -68,12 +68,12 @@ zx_status_t sys_resource_create(zx_handle_t parent_rsrc,
 
     // Create a new Resource
     zx_rights_t rights;
-    fbl::RefPtr<ResourceDispatcher> child;
-    status = ResourceDispatcher::Create(&child, &rights, kind, base, size, flags, name);
+    KernelHandle<ResourceDispatcher> handle;
+    status = ResourceDispatcher::Create(&handle, &rights, kind, base, size, flags, name);
     if (status != ZX_OK) {
         return status;
     }
 
     // Create a handle for the child
-    return resource_out->make(ktl::move(child), rights);
+    return resource_out->make(ktl::move(handle), rights);
 }
diff --git a/zircon/kernel/tests/resource_tests.cpp b/zircon/kernel/tests/resource_tests.cpp
index cb085f088c8198a59f245ed5b5f7a1493dfe00e8..83eab283a8d9dcceddfe7e781ed66c58a90c88f9 100644
--- a/zircon/kernel/tests/resource_tests.cpp
+++ b/zircon/kernel/tests/resource_tests.cpp
@@ -8,6 +8,7 @@
 
 #include <fbl/alloc_checker.h>
 #include <ktl/unique_ptr.h>
+#include <object/handle.h>
 #include <object/resource_dispatcher.h>
 #include <lib/unittest/unittest.h>
 
@@ -17,12 +18,11 @@ static bool unconfigured() {
     ResourceDispatcher::ResourceList test_resource_list;
     zx_rights_t rights;
 
-    ResourceDispatcher::RefPtr disp1, disp2;
-    EXPECT_EQ(ResourceDispatcher::Create(&disp1, &rights, ZX_RSRC_KIND_MMIO,  0, PAGE_SIZE, 0,
+    KernelHandle<ResourceDispatcher> handle1, handle2;
+    EXPECT_EQ(ResourceDispatcher::Create(&handle1, &rights, ZX_RSRC_KIND_MMIO,  0, PAGE_SIZE, 0,
                 NULL, test_rallocs, &test_resource_list),
             ZX_ERR_BAD_STATE, "MMIO GetRegion should return ERR_BAD_STATE");
-    ResourceDispatcher::RefPtr disp;
-    EXPECT_EQ(ResourceDispatcher::Create(&disp2, &rights, ZX_RSRC_KIND_IRQ, 0, PAGE_SIZE, 0,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle2, &rights, ZX_RSRC_KIND_IRQ, 0, PAGE_SIZE, 0,
                 NULL, test_rallocs, &test_resource_list),
             ZX_ERR_BAD_STATE, "IRQ GetRegion should return ERR_BAD_STATE");
     // Nothing should be in the lists.
@@ -56,7 +56,7 @@ static bool exclusive_then_shared() {
     ResourceDispatcher::ResourceList test_resource_list;
     RegionAllocator test_rallocs[ZX_RSRC_KIND_COUNT];
 
-    ResourceDispatcher::RefPtr disp1, disp2;
+    KernelHandle<ResourceDispatcher> handle1, handle2;
     zx_rights_t rights;
     uint64_t base = 0;
     uint64_t size = PAGE_SIZE;
@@ -65,14 +65,14 @@ static bool exclusive_then_shared() {
                 test_rallocs),
             ZX_OK, "");
     // Creating the exclusive resource will succeed.
-    EXPECT_EQ(ResourceDispatcher::Create(&disp1, &rights, ZX_RSRC_KIND_MMIO, base, size,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle1, &rights, ZX_RSRC_KIND_MMIO, base, size,
                 flags, "ets-disp1", test_rallocs, &test_resource_list),
             ZX_OK, "Creating the exclusive resource failed.");
 
     EXPECT_EQ(test_resource_list.size_slow(), 1u, "");
     // Creating the shared resource should fail
     flags = 0;
-    EXPECT_EQ(ResourceDispatcher::Create(&disp2, &rights, ZX_RSRC_KIND_MMIO, base, size,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle2, &rights, ZX_RSRC_KIND_MMIO, base, size,
                 flags, "ets-disp2", test_rallocs, &test_resource_list),
             ZX_ERR_NOT_FOUND, "Creating the shared resource succeeded.");
 
@@ -87,7 +87,7 @@ static bool shared_then_exclusive() {
     ResourceDispatcher::ResourceList test_resource_list;
     RegionAllocator test_rallocs[ZX_RSRC_KIND_COUNT];
 
-    ResourceDispatcher::RefPtr disp1, disp2;
+    KernelHandle<ResourceDispatcher> handle1, handle2;
     zx_rights_t rights;
     uint64_t base = 0;
     uint64_t size = PAGE_SIZE;
@@ -96,14 +96,14 @@ static bool shared_then_exclusive() {
                 test_rallocs),
             ZX_OK, "");
     // Creating the shared resource will succeed.
-    EXPECT_EQ(ResourceDispatcher::Create(&disp1, &rights, ZX_RSRC_KIND_MMIO, base, size,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle1, &rights, ZX_RSRC_KIND_MMIO, base, size,
                 flags, "ets-disp1", test_rallocs, &test_resource_list),
             ZX_OK, "Creating the exclusive resource failed.");
 
     EXPECT_EQ(test_resource_list.size_slow(), 1u, "");
     // Creating the exclusive resource should fail
     flags = ZX_RSRC_FLAG_EXCLUSIVE;
-    EXPECT_EQ(ResourceDispatcher::Create(&disp2, &rights, ZX_RSRC_KIND_MMIO, base, size,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle2, &rights, ZX_RSRC_KIND_MMIO, base, size,
                 flags, "ets-disp2", test_rallocs, &test_resource_list),
             ZX_ERR_NOT_FOUND, "Creating the shared resource succeeded.");
 
@@ -117,19 +117,19 @@ static bool out_of_allocator_range() {
 
     ResourceDispatcher::ResourceList test_resource_list;
     RegionAllocator test_rallocs[ZX_RSRC_KIND_COUNT];
-    ResourceDispatcher::RefPtr disp1;
+    KernelHandle<ResourceDispatcher> handle1;
     zx_rights_t rights;
     uint64_t size = 0xFFFF;
 
     ASSERT_EQ(ResourceDispatcher::InitializeAllocator(ZX_RSRC_KIND_MMIO, 0, size, test_rallocs),
               ZX_OK, "");
     // Overlap near the end
-    EXPECT_EQ(ResourceDispatcher::Create(&disp1, &rights, ZX_RSRC_KIND_MMIO, size - 0xFF, 0xFFF,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle1, &rights, ZX_RSRC_KIND_MMIO, size - 0xFF, 0xFFF,
                                          0, "ooar-disp1", test_rallocs, &test_resource_list),
               ZX_ERR_NOT_FOUND, "");
 
     // Pick a chunk outside the range entirely
-    EXPECT_EQ(ResourceDispatcher::Create(&disp1, &rights, ZX_RSRC_KIND_MMIO, size + size, size,
+    EXPECT_EQ(ResourceDispatcher::Create(&handle1, &rights, ZX_RSRC_KIND_MMIO, size + size, size,
                                          0, "ooar-disp1", test_rallocs, &test_resource_list),
               ZX_ERR_NOT_FOUND, "");