|
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 |
|
17 | | - |
| 17 | +/** |
| 18 | + * Fast {@link StreamingXXHash32} implemented with JNI bindings. |
| 19 | + * The methods are synchronized to avoid a race condition |
| 20 | + * between freeing the native memory in finalize() and using it in |
| 21 | + * reset(), getValue(), and update(). Note that GC can call finalize() |
| 22 | + * after calling checkState() and before using XXHashJNI if the caller |
| 23 | + * does not retain a reference to this object. |
| 24 | + */ |
18 | 25 | final class StreamingXXHash32JNI extends StreamingXXHash32 { |
19 | 26 |
|
20 | 27 | static class Factory implements StreamingXXHash32.Factory { |
@@ -42,26 +49,26 @@ private void checkState() { |
42 | 49 | } |
43 | 50 |
|
44 | 51 | @Override |
45 | | - public void reset() { |
| 52 | + public synchronized void reset() { |
46 | 53 | checkState(); |
47 | 54 | XXHashJNI.XXH32_free(state); |
48 | 55 | state = XXHashJNI.XXH32_init(seed); |
49 | 56 | } |
50 | 57 |
|
51 | 58 | @Override |
52 | | - public int getValue() { |
| 59 | + public synchronized int getValue() { |
53 | 60 | checkState(); |
54 | 61 | return XXHashJNI.XXH32_digest(state); |
55 | 62 | } |
56 | 63 |
|
57 | 64 | @Override |
58 | | - public void update(byte[] bytes, int off, int len) { |
| 65 | + public synchronized void update(byte[] bytes, int off, int len) { |
59 | 66 | checkState(); |
60 | 67 | XXHashJNI.XXH32_update(state, bytes, off, len); |
61 | 68 | } |
62 | 69 |
|
63 | 70 | @Override |
64 | | - protected void finalize() throws Throwable { |
| 71 | + protected synchronized void finalize() throws Throwable { |
65 | 72 | super.finalize(); |
66 | 73 | // free memory |
67 | 74 | XXHashJNI.XXH32_free(state); |
|
0 commit comments