|
5 | 5 | import java.security.SecureRandom; |
6 | 6 | import java.time.Duration; |
7 | 7 | import java.time.Instant; |
| 8 | +import java.lang.invoke.MethodHandles; |
| 9 | +import java.lang.invoke.VarHandle; |
8 | 10 | import java.util.Arrays; |
9 | 11 | import java.util.Map; |
10 | 12 | import java.util.concurrent.CompletableFuture; |
@@ -178,7 +180,6 @@ public int getOperationCount() { |
178 | 180 | /** |
179 | 181 | * Guard an operation with usability checks and operation counting. Verifies the cached key is not |
180 | 182 | * closed or expired before running the operation, and increments the operation count on success. |
181 | | - * |
182 | 183 | * @param operation The operation to perform |
183 | 184 | * @param countOps Extracts the number of successful operations from the result |
184 | 185 | * @param counter The counter to increment on success |
@@ -312,14 +313,15 @@ public void close() { |
312 | 313 | } |
313 | 314 |
|
314 | 315 | /** |
315 | | - * Zero a DEK byte array with a subsequent access to prevent the JIT from eliminating the fill as |
316 | | - * a dead store. The volatile write after the fill ensures the zeroing is not optimized away. |
| 316 | + * Zero a DEK byte array using opaque stores to prevent the JIT from eliminating the writes as |
| 317 | + * dead stores. VarHandle.setOpaque is the lightest memory ordering mode that guarantees the |
| 318 | + * writes actually happen per the Java Memory Model spec. |
317 | 319 | */ |
318 | | - @SuppressWarnings("unused") |
319 | | - private static volatile byte ZERO_FENCE; |
| 320 | + private static final VarHandle BYTE_ARRAY = MethodHandles.arrayElementVarHandle(byte[].class); |
320 | 321 |
|
321 | 322 | static void zeroDek(byte[] dek) { |
322 | | - Arrays.fill(dek, (byte) 0); |
323 | | - ZERO_FENCE = dek[0]; |
| 323 | + for (int i = 0; i < dek.length; i++) { |
| 324 | + BYTE_ARRAY.setOpaque(dek, i, (byte) 0); |
| 325 | + } |
324 | 326 | } |
325 | 327 | } |
0 commit comments