diff a/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java b/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java
--- a/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java
+++ b/test/jdk/java/util/Arrays/largeMemory/ParallelPrefix.java
@@ -24,10 +24,11 @@
 /*
  * @test
  * @bug 8014076 8025067
  * @summary unit test for Arrays.ParallelPrefix().
  * @modules java.management jdk.management
+ * @library /test/lib
  * @run junit/othervm -Xms256m -Xmx1024m ParallelPrefix
  */
 
 import java.lang.management.ManagementFactory;
 import java.util.Arrays;
@@ -38,10 +39,12 @@
 import java.util.function.LongBinaryOperator;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
 import com.sun.management.OperatingSystemMXBean;
 
+import jdk.test.lib.valueclass.AsValueClass;
+
 import static org.junit.jupiter.api.Assertions.*;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.function.Executable;
@@ -62,10 +65,13 @@
     //Array size much greater than MIN_PARTITION
     private static final int LARGE_ARRAY_SIZE = 1 << 14;
 
     private static int[] arraySizeCollection;
 
+    @AsValueClass
+    record VInt(int value) {}
+
     @BeforeAll
     public static void setup() {
         java.lang.management.OperatingSystemMXBean bean =
                 ManagementFactory.getOperatingSystemMXBean();
         if (bean instanceof OperatingSystemMXBean) {
@@ -140,10 +146,19 @@
             }
         }
         return data;
     }
 
+    public static Object[][] valueSet() {
+        Function<Integer, VInt[]> vIntFunc = size ->
+                IntStream.range(0, size).mapToObj(VInt::new).toArray(VInt[]::new);
+        BinaryOperator<VInt> sumOp = (a, b) -> new VInt(a.value() + b.value());
+        BinaryOperator<VInt> minOp = (a, b) -> a.value() <= b.value() ? a : b;
+        return genericData(vIntFunc,
+                (BinaryOperator<VInt>[]) new BinaryOperator[]{sumOp, minOp});
+    }
+
     @ParameterizedTest
     @MethodSource("intSet")
     public void testParallelPrefixForInt(int[] data, int fromIndex, int toIndex, IntBinaryOperator op) {
         int[] sequentialResult = data.clone();
         for (int index = fromIndex + 1; index < toIndex; index++) {
@@ -208,58 +223,82 @@
         String[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex);
         Arrays.parallelPrefix(parallelRangeResult, op);
         assertArraysEqual(Arrays.copyOfRange(sequentialResult, fromIndex, toIndex), parallelRangeResult);
     }
 
+    @ParameterizedTest
+    @MethodSource("valueSet")
+    public void testParallelPrefixForValue(VInt[] data, int fromIndex, int toIndex, BinaryOperator<VInt> op) {
+        VInt[] sequentialResult = data.clone();
+        for (int index = fromIndex + 1; index < toIndex; index++) {
+            sequentialResult[index] = op.apply(sequentialResult[index - 1], sequentialResult[index]);
+        }
+
+        VInt[] parallelResult = data.clone();
+        Arrays.parallelPrefix(parallelResult, fromIndex, toIndex, op);
+        assertArraysEqual(parallelResult, sequentialResult);
+
+        VInt[] parallelRangeResult = Arrays.copyOfRange(data, fromIndex, toIndex);
+        Arrays.parallelPrefix(parallelRangeResult, op);
+        assertArraysEqual(parallelRangeResult, Arrays.copyOfRange(sequentialResult, fromIndex, toIndex));
+    }
+
     @Test
     public void testNPEs() {
         // null array
         assertThrowsNPE(() -> Arrays.parallelPrefix((int[]) null, Integer::max));
         assertThrowsNPE(() -> Arrays.parallelPrefix((long []) null, Long::max));
         assertThrowsNPE(() -> Arrays.parallelPrefix((double []) null, Double::max));
         assertThrowsNPE(() -> Arrays.parallelPrefix((String []) null, String::concat));
+        assertThrowsNPE(() -> Arrays.parallelPrefix((VInt[]) null, (a, b) -> new VInt(a.value() + b.value())));
 
         // null array w/ range
         assertThrowsNPE(() -> Arrays.parallelPrefix((int[]) null, 0, 0, Integer::max));
         assertThrowsNPE(() -> Arrays.parallelPrefix((long []) null, 0, 0, Long::max));
         assertThrowsNPE(() -> Arrays.parallelPrefix((double []) null, 0, 0, Double::max));
         assertThrowsNPE(() -> Arrays.parallelPrefix((String []) null, 0, 0, String::concat));
+        assertThrowsNPE(() -> Arrays.parallelPrefix((VInt[]) null, 0, 0, (a, b) -> new VInt(a.value() + b.value())));
 
         // null op
         assertThrowsNPE(() -> Arrays.parallelPrefix(new int[] {}, null));
         assertThrowsNPE(() -> Arrays.parallelPrefix(new long[] {}, null));
         assertThrowsNPE(() -> Arrays.parallelPrefix(new double[] {}, null));
         assertThrowsNPE(() -> Arrays.parallelPrefix(new String[] {}, null));
+        assertThrowsNPE(() -> Arrays.parallelPrefix(new VInt[] {}, (BinaryOperator<VInt>) null));
 
         // null op w/ range
         assertThrowsNPE(() -> Arrays.parallelPrefix(new int[] {}, 0, 0, null));
         assertThrowsNPE(() -> Arrays.parallelPrefix(new long[] {}, 0, 0, null));
         assertThrowsNPE(() -> Arrays.parallelPrefix(new double[] {}, 0, 0, null));
         assertThrowsNPE(() -> Arrays.parallelPrefix(new String[] {}, 0, 0, null));
+        assertThrowsNPE(() -> Arrays.parallelPrefix(new VInt[] {}, 0, 0, (BinaryOperator<VInt>) null));
     }
 
     @Test
     public void testIAEs() {
         assertThrowsIAE(() -> Arrays.parallelPrefix(new int[] {}, 1, 0, Integer::max));
         assertThrowsIAE(() -> Arrays.parallelPrefix(new long[] {}, 1, 0, Long::max));
         assertThrowsIAE(() -> Arrays.parallelPrefix(new double[] {}, 1, 0, Double::max));
         assertThrowsIAE(() -> Arrays.parallelPrefix(new String[] {}, 1, 0, String::concat));
+        assertThrowsIAE(() -> Arrays.parallelPrefix(new VInt[] {}, 1, 0, (a, b) -> new VInt(a.value() + b.value())));
     }
 
     @Test
     public void testAIOOBEs() {
         // bad "fromIndex"
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new int[] {}, -1, 0, Integer::max));
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new long[] {}, -1, 0, Long::max));
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new double[] {}, -1, 0, Double::max));
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new String[] {}, -1, 0, String::concat));
+        assertThrowsAIOOB(() -> Arrays.parallelPrefix(new VInt[] {}, -1, 0, (a, b) -> new VInt(a.value() + b.value())));
 
         // bad "toIndex"
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new int[] {}, 0, 1, Integer::max));
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new long[] {}, 0, 1, Long::max));
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new double[] {}, 0, 1, Double::max));
         assertThrowsAIOOB(() -> Arrays.parallelPrefix(new String[] {}, 0, 1, String::concat));
+        assertThrowsAIOOB(() -> Arrays.parallelPrefix(new VInt[] {}, 0, 1, (a, b) -> new VInt(a.value() + b.value())));
     }
 
     // "library" code
 
     private void assertThrowsNPE(Executable r) {
@@ -307,7 +346,16 @@
         } catch (AssertionError x) {
             throw new AssertionError(String.format("Expected:%s, actual:%s",
                     Arrays.toString(expected), Arrays.toString(actual)), x);
         }
     }
+
+    static void assertArraysEqual(VInt[] actual, VInt[] expected) {
+        try {
+            assertArrayEquals(actual, expected, "");
+        } catch (AssertionError x) {
+            throw new AssertionError(String.format("Expected:%s, actual:%s",
+                    Arrays.toString(expected), Arrays.toString(actual)), x);
+        }
+    }
 }
 
