diff --git a/pom.xml b/pom.xml
index cbdcac32..60ea1466 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,7 @@
io
net
os
+ ref
version
vertx-context
diff --git a/ref/pom.xml b/ref/pom.xml
new file mode 100644
index 00000000..918b8d17
--- /dev/null
+++ b/ref/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+
+ io.smallrye.common
+ smallrye-common-parent
+ 1.10.1-SNAPSHOT
+
+
+ smallrye-common-ref
+
+ SmallRye Common: References
+
+
+
+ ${project.groupId}
+ smallrye-common-constraint
+
+
+
+
+
+ coverage
+
+ @{jacocoArgLine}
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ report
+ verify
+
+ report
+
+
+
+
+
+
+
+
+
diff --git a/ref/src/main/java/io/smallrye/common/ref/CleanerReference.java b/ref/src/main/java/io/smallrye/common/ref/CleanerReference.java
new file mode 100644
index 00000000..0142744a
--- /dev/null
+++ b/ref/src/main/java/io/smallrye/common/ref/CleanerReference.java
@@ -0,0 +1,37 @@
+package io.smallrye.common.ref;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * A special version of {@link PhantomReference} that is strongly retained until it is reaped by the collection thread.
+ */
+public class CleanerReference extends PhantomReference {
+ private static final Set> set = Collections
+ .newSetFromMap(new ConcurrentHashMap, Boolean>());
+
+ /**
+ * Construct a new instance with a reaper.
+ *
+ * @param referent the referent
+ * @param attachment the attachment
+ * @param reaper the reaper to use
+ */
+ public CleanerReference(final T referent, final A attachment, final Reaper reaper) {
+ super(referent, attachment, reaper);
+ set.add(this);
+ }
+
+ void clean() {
+ set.remove(this);
+ }
+
+ public final int hashCode() {
+ return super.hashCode();
+ }
+
+ public final boolean equals(final Object obj) {
+ return super.equals(obj);
+ }
+}
diff --git a/ref/src/main/java/io/smallrye/common/ref/PhantomReference.java b/ref/src/main/java/io/smallrye/common/ref/PhantomReference.java
new file mode 100644
index 00000000..67722743
--- /dev/null
+++ b/ref/src/main/java/io/smallrye/common/ref/PhantomReference.java
@@ -0,0 +1,59 @@
+package io.smallrye.common.ref;
+
+import java.lang.ref.ReferenceQueue;
+
+/**
+ * A reapable phantom reference with an attachment. If a {@link Reaper} is given, then it will be used to asynchronously
+ * clean up the referent.
+ *
+ * @param the reference value type
+ * @param the attachment type
+ *
+ * @see java.lang.ref.PhantomReference
+ */
+public class PhantomReference extends java.lang.ref.PhantomReference implements Reference, Reapable {
+ private final A attachment;
+ private final Reaper reaper;
+
+ /**
+ * Construct a new instance with an explicit reference queue.
+ *
+ * @param referent the referent
+ * @param attachment the attachment
+ * @param q the reference queue to use
+ */
+ public PhantomReference(final T referent, final A attachment, final ReferenceQueue super T> q) {
+ super(referent, q);
+ this.attachment = attachment;
+ reaper = null;
+ }
+
+ /**
+ * Construct a new instance with a reaper.
+ *
+ * @param referent the referent
+ * @param attachment the attachment
+ * @param reaper the reaper to use
+ */
+ public PhantomReference(final T referent, final A attachment, final Reaper reaper) {
+ super(referent, References.ReaperThread.REAPER_QUEUE);
+ this.reaper = reaper;
+ this.attachment = attachment;
+ }
+
+ public A getAttachment() {
+ return attachment;
+ }
+
+ public Type getType() {
+ return Type.PHANTOM;
+ }
+
+ public Reaper getReaper() {
+ return reaper;
+ }
+
+ public String toString() {
+ return "phantom reference";
+ }
+}
diff --git a/ref/src/main/java/io/smallrye/common/ref/Reapable.java b/ref/src/main/java/io/smallrye/common/ref/Reapable.java
new file mode 100644
index 00000000..216c9bf8
--- /dev/null
+++ b/ref/src/main/java/io/smallrye/common/ref/Reapable.java
@@ -0,0 +1,17 @@
+package io.smallrye.common.ref;
+
+/**
+ * A reference which is reapable (can be automatically collected).
+ *
+ * @param the reference type
+ * @param the reference attachment type
+ */
+interface Reapable {
+
+ /**
+ * Get the associated reaper.
+ *
+ * @return the reaper
+ */
+ Reaper getReaper();
+}
diff --git a/ref/src/main/java/io/smallrye/common/ref/Reaper.java b/ref/src/main/java/io/smallrye/common/ref/Reaper.java
new file mode 100644
index 00000000..a07b7dd7
--- /dev/null
+++ b/ref/src/main/java/io/smallrye/common/ref/Reaper.java
@@ -0,0 +1,17 @@
+package io.smallrye.common.ref;
+
+/**
+ * A cleaner for a dead object.
+ *
+ * @param the reference type
+ * @param the reference attachment type
+ */
+public interface Reaper {
+
+ /**
+ * Perform the cleanup action for a reference.
+ *
+ * @param reference the reference
+ */
+ void reap(Reference reference);
+}
diff --git a/ref/src/main/java/io/smallrye/common/ref/Reference.java b/ref/src/main/java/io/smallrye/common/ref/Reference.java
new file mode 100644
index 00000000..2365c7c6
--- /dev/null
+++ b/ref/src/main/java/io/smallrye/common/ref/Reference.java
@@ -0,0 +1,135 @@
+package io.smallrye.common.ref;
+
+import java.util.EnumSet;
+
+/**
+ * An enhanced reference type with a type-safe attachment.
+ *
+ * @param the reference value type
+ * @param the attachment type
+ *
+ * @see java.lang.ref.Reference
+ */
+public interface Reference {
+
+ /**
+ * Get the value, or {@code null} if the reference has been cleared.
+ *
+ * @return the value
+ */
+ T get();
+
+ /**
+ * Get the attachment, if any.
+ *
+ * @return the attachment
+ */
+ A getAttachment();
+
+ /**
+ * Clear the reference.
+ */
+ void clear();
+
+ /**
+ * Get the type of the reference.
+ *
+ * @return the type
+ */
+ Type getType();
+
+ /**
+ * A reference type.
+ *
+ * @apiviz.exclude
+ */
+ enum Type {
+
+ /**
+ * A strong reference.
+ */
+ STRONG,
+ /**
+ * A weak reference.
+ */
+ WEAK,
+ /**
+ * A phantom reference.
+ */
+ PHANTOM,
+ /**
+ * A soft reference.
+ */
+ SOFT,
+ /**
+ * A {@code null} reference.
+ */
+ NULL,
+ ;
+
+ private static final int fullSize = values().length;
+
+ /**
+ * Determine whether the given set is fully populated (or "full"), meaning it contains all possible values.
+ *
+ * @param set the set
+ *
+ * @return {@code true} if the set is full, {@code false} otherwise
+ */
+ public static boolean isFull(final EnumSet set) {
+ return set != null && set.size() == fullSize;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param v1 the first instance
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final Type v1) {
+ return this == v1;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param v1 the first instance
+ * @param v2 the second instance
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final Type v1, final Type v2) {
+ return this == v1 || this == v2;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param v1 the first instance
+ * @param v2 the second instance
+ * @param v3 the third instance
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final Type v1, final Type v2, final Type v3) {
+ return this == v1 || this == v2 || this == v3;
+ }
+
+ /**
+ * Determine whether this instance is equal to one of the given instances.
+ *
+ * @param values the possible values
+ *
+ * @return {@code true} if one of the instances matches this one, {@code false} otherwise
+ */
+ public boolean in(final Type... values) {
+ if (values != null)
+ for (Type value : values) {
+ if (this == value)
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/ref/src/main/java/io/smallrye/common/ref/References.java b/ref/src/main/java/io/smallrye/common/ref/References.java
new file mode 100644
index 00000000..1ac18f1b
--- /dev/null
+++ b/ref/src/main/java/io/smallrye/common/ref/References.java
@@ -0,0 +1,176 @@
+package io.smallrye.common.ref;
+
+import static java.security.AccessController.doPrivileged;
+
+import java.lang.ref.ReferenceQueue;
+import java.security.PrivilegedAction;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import io.smallrye.common.constraint.Assert;
+
+/**
+ * A set of utility methods for reference types.
+ */
+public final class References {
+ private References() {
+ }
+
+ private static final Reference, ?> NULL = new StrongReference<>(null);
+
+ static final class ReaperThread extends Thread {
+ static final ReferenceQueue