diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index ee3da58e2dd..7fc31c63b56 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -8188,19 +8188,18 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * filter function and the target var handle is then called on the modified (usually shortened)
      * coordinate list.
      * <p>
-     * If {@code R} is the return type of the filter (which cannot be void), the target var handle must accept a value of
-     * type {@code R} as its coordinate in position {@code pos}, preceded and/or followed by
-     * any coordinate not passed to the filter.
-     * No coordinates are reordered, and the result returned from the filter
-     * replaces (in order) the whole subsequence of coordinates originally
-     * passed to the adapter.
-     * <p>
-     * The argument types (if any) of the filter
-     * replace zero or one coordinate types of the target var handle, at position {@code pos},
-     * in the resulting adapted var handle.
-     * The return type of the filter must be identical to the
-     * coordinate type of the target var handle at position {@code pos}, and that target var handle
-     * coordinate is supplied by the return value of the filter.
+     * If {@code R} is the return type of the filter, then:
+     * <ul>
+     * <li>if {@code R} <em>is not</em> {@code void}, the target var handle must have a coordinate of type {@code R} in
+     * position {@code pos}. The parameter types of the filter will replace the coordinate type at position {@code pos}
+     * of the target var handle. When the returned var handle is invoked, it will be as if the filter is invoked first,
+     * and its result is passed in place of the coordinate at position {@code pos} in a downstream invocation of the
+     * target var handle.</li>
+     * <li> if {@code R} <em>is</em> {@code void}, the parameter types (if any) of the filter will be inserted in the
+     * coordinate type list of the target var handle at position {@code pos}. In this case, when the returned var handle
+     * is invoked, the filter essentially acts as a side effect, consuming some of the coordinate values, before a
+     * downstream invocation of the target var handle.</li>
+     * </ul>
      * <p>
      * If any of the filters throws a checked exception when invoked, the resulting var handle will
      * throw an {@link IllegalStateException}.
@@ -8209,12 +8208,12 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * atomic access guarantees as those featured by the target var handle.
      *
      * @param target the var handle to invoke after the coordinates have been filtered
-     * @param pos the position of the coordinate to be filtered
+     * @param pos the position in the coordinate list of the target var handle where the filter is to be inserted
      * @param filter the filter method handle
      * @return an adapter var handle which filters the incoming coordinate values,
      * before calling the target var handle
      * @throws IllegalArgumentException if the return type of {@code filter}
-     * is void, or it is not the same as the {@code pos} coordinate of the target var handle,
+     * is not void, and it is not the same as the {@code pos} coordinate of the target var handle,
      * if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
      * if the resulting var handle's type would have <a href="MethodHandle.html#maxarity">too many coordinates</a>,
      * or if it's determined that {@code filter} throws any checked exceptions.
diff --git a/src/java.base/share/classes/java/lang/invoke/VarHandles.java b/src/java.base/share/classes/java/lang/invoke/VarHandles.java
index a8bc817a9e7..13993ca8f10 100644
--- a/src/java.base/share/classes/java/lang/invoke/VarHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandles.java
@@ -563,14 +563,14 @@ final class VarHandles {
         List<Class<?>> targetCoordinates = target.coordinateTypes();
         if (pos < 0 || pos >= targetCoordinates.size()) {
             throw newIllegalArgumentException("Invalid position " + pos + " for coordinate types", targetCoordinates);
-        } else if (filter.type().returnType() == void.class) {
-            throw newIllegalArgumentException("Invalid filter type " + filter.type() + " ; filter cannot be void");
-        } else if (filter.type().returnType() != targetCoordinates.get(pos)) {
+        } else if (filter.type().returnType() != void.class && filter.type().returnType() != targetCoordinates.get(pos)) {
             throw newIllegalArgumentException("Invalid filter type " + filter.type() + " for coordinate type " + targetCoordinates.get(pos));
         }
 
         List<Class<?>> newCoordinates = new ArrayList<>(targetCoordinates);
-        newCoordinates.remove(pos);
+        if (filter.type().returnType() != void.class) {
+            newCoordinates.remove(pos);
+        }
         newCoordinates.addAll(pos, filter.type().parameterList());
 
         return new IndirectVarHandle(target, target.varType(), newCoordinates.toArray(new Class<?>[0]),
diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java
index 893755f15d4..5074b8d793b 100644
--- a/test/jdk/java/foreign/TestAdaptVarHandles.java
+++ b/test/jdk/java/foreign/TestAdaptVarHandles.java
@@ -351,6 +351,12 @@ public class TestAdaptVarHandles {
         assertEquals(value, 42);
     }
 
+    @Test
+    public void testCollectCoordinatesVoidFilterType() {
+        VarHandle handle = MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER);
+        assertEquals(handle.coordinateTypes(), List.of(String.class, MemorySegment.class));
+    }
+
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testBadCollectCoordinatesNegativePos() {
         MethodHandles.collectCoordinates(intHandle, -1, SUM_OFFSETS);
@@ -366,11 +372,6 @@ public class TestAdaptVarHandles {
         MethodHandles.collectCoordinates(intHandle, 0, SUM_OFFSETS);
     }
 
-    @Test(expectedExceptions = IllegalArgumentException.class)
-    public void testBadCollectCoordinatesWrongVoidFilterType() {
-        MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER);
-    }
-
     @Test(expectedExceptions = IllegalArgumentException.class)
     public void testBadCollectCoordinatesWrongFilterException() {
         MethodHandles.collectCoordinates(intHandle, 0, S2L_EX);