|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
@@ -62,8 +62,11 @@ public class ModuleReferenceImpl extends ModuleReference {
|
62 | 62 | // ModuleResolution flags
|
63 | 63 | private final ModuleResolution moduleResolution;
|
64 | 64 |
|
65 |
| - // cached hash of this module to avoid needing to compute it many times |
66 |
| - private byte[] cachedHash; |
| 65 | + // Single-slot cache of this module's hash to avoid needing to compute |
| 66 | + // it many times. For correctness under concurrent updates, we need to |
| 67 | + // wrap the fields updated at the same time with a record. |
| 68 | + private record CachedHash(byte[] hash, String algorithm) {} |
| 69 | + private CachedHash cachedHash; |
67 | 70 |
|
68 | 71 | /**
|
69 | 72 | * Constructs a new instance of this class.
|
@@ -139,13 +142,17 @@ public ModuleResolution moduleResolution() {
|
139 | 142 | * @throws java.io.UncheckedIOException if an I/O error occurs
|
140 | 143 | */
|
141 | 144 | public byte[] computeHash(String algorithm) {
|
142 |
| - byte[] result = cachedHash; |
143 |
| - if (result != null) |
144 |
| - return result; |
145 |
| - if (hasher == null) |
| 145 | + CachedHash ch = cachedHash; |
| 146 | + if (ch != null && ch.algorithm().equals(algorithm)) { |
| 147 | + return ch.hash(); |
| 148 | + } |
| 149 | + |
| 150 | + if (hasher == null) { |
146 | 151 | return null;
|
147 |
| - cachedHash = result = hasher.generate(algorithm); |
148 |
| - return result; |
| 152 | + } |
| 153 | + byte[] hash = hasher.generate(algorithm); |
| 154 | + cachedHash = new CachedHash(hash, algorithm); |
| 155 | + return hash; |
149 | 156 | }
|
150 | 157 |
|
151 | 158 | @Override
|
|
0 commit comments