11/*
2- * Copyright (c) 2011, 2013 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2011, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2121 * questions.
2222 */
2323
24- /* @test
24+ /*
25+ * @test
26+ * @bug 8351045
2527 * @summary tests for class-specific values
26- * @compile ClassValueTest.java
27- * @run testng/othervm test.java.lang.invoke.ClassValueTest
28+ * @run junit ClassValueTest
2829 */
2930
30- package test .java .lang .invoke ;
31+ import java .util .ArrayList ;
32+ import java .util .concurrent .ExecutionException ;
33+ import java .util .concurrent .Executors ;
34+ import java .util .concurrent .Future ;
35+ import java .util .concurrent .atomic .AtomicInteger ;
36+
37+ import org .junit .jupiter .api .Test ;
3138
32- import org .testng .*;
33- import static org .testng .AssertJUnit .*;
34- import org .testng .annotations .*;
39+ import static org .junit .jupiter .api .Assertions .assertEquals ;
3540
3641/**
3742 * @author jrose
3843 */
39- public class ClassValueTest {
44+ final class ClassValueTest {
4045 static String nameForCV1 (Class <?> type ) {
4146 return "CV1:" + type .getName ();
4247 }
@@ -143,7 +148,7 @@ public void testGetMany() {
143148 }
144149 }
145150 }
146- assertEquals (countForCVN , 0 );
151+ assertEquals (0 , countForCVN );
147152 System .out .println ("[rechecking values]" );
148153 for (int i = 0 ; i < cvns .length * 10 ; i ++) {
149154 int n = i % cvns .length ;
@@ -152,4 +157,57 @@ public void testGetMany() {
152157 }
153158 }
154159 }
160+
161+ private static final int RUNS = 16 ;
162+ private static final long COMPUTE_TIME_MILLIS = 100 ;
163+
164+ @ Test
165+ void testRemoveOnComputeCases () {
166+ try (var exec = Executors .newVirtualThreadPerTaskExecutor ()) {
167+ var tasks = new ArrayList <Future <?>>(RUNS );
168+ for (int i = 0 ; i < RUNS ; i ++) {
169+ tasks .add (exec .submit (this ::testRemoveOnCompute ));
170+ }
171+ for (var task : tasks ) {
172+ try {
173+ task .get ();
174+ } catch (InterruptedException | ExecutionException ex ) {
175+ var cause = ex .getCause ();
176+ if (cause instanceof AssertionError ae )
177+ throw ae ;
178+ throw new RuntimeException (ex );
179+ }
180+ }
181+ }
182+ }
183+
184+ void testRemoveOnCompute () {
185+ AtomicInteger input = new AtomicInteger (0 );
186+ ClassValue <Integer > cv = new ClassValue <>() {
187+ @ Override
188+ protected Integer computeValue (Class <?> type ) {
189+ // must get early to represent using outdated input
190+ int v = input .get ();
191+ try {
192+ Thread .sleep (COMPUTE_TIME_MILLIS );
193+ } catch (InterruptedException ex ) {
194+ throw new RuntimeException (ex );
195+ }
196+ return v ;
197+ }
198+ };
199+ var innocuous = Thread .startVirtualThread (() -> cv .get (int .class ));
200+ var refreshInput = Thread .startVirtualThread (() -> {
201+ input .incrementAndGet ();
202+ cv .remove (int .class ); // Let's recompute with updated inputs!
203+ });
204+ try {
205+ innocuous .join ();
206+ refreshInput .join ();
207+ } catch (InterruptedException ex ) {
208+ throw new RuntimeException (ex );
209+ }
210+ assertEquals (1 , input .get (), "input not updated" );
211+ assertEquals (1 , cv .get (int .class ), "CV not using up-to-date input" );
212+ }
155213}
0 commit comments