Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc91893a

Browse files
committed
Fix transient pointer deallocation in ByteArrayProxy
JNR-FFI's TransientNativeMemory was prematurely deallocating off-heapmemory before LMDB syscalls completed. Return transient pointers fromBufferProxy.in() and use reachability fencing at all call sites toprevent premature GC.BufferProxy and KeyVal were also simplified to remove pointer addresspassing, given this is inexpensively available from thePointer.address() accessor (which is backed by a final field).This is an API breaking change if external users implemented their ownBufferProxy, however it is considered unlikely many (if any) userswould have ever done this.Fixes#252
1 parent1ea5902 commitc91893a

File tree

9 files changed

+91
-57
lines changed

9 files changed

+91
-57
lines changed

‎src/main/java/org/lmdbjava/BufferProxy.java‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,30 +107,29 @@ protected Comparator<T> getComparator(DbiFlags... flags) {
107107
*
108108
* @param buffer the buffer to write to <code>MDB_val</code>
109109
* @param ptr the pointer to the <code>MDB_val</code>
110-
* @param ptrAddr the address of the <code>MDB_val</code> pointer
110+
* @return a transient pointer that must be kept alive, or null if none
111111
*/
112-
protectedabstractvoidin(Tbuffer,Pointerptr,longptrAddr);
112+
protectedabstractPointerin(Tbuffer,Pointerptr);
113113

114114
/**
115115
* Called when the <code>MDB_val</code> should be set to reflect the passed buffer.
116116
*
117117
* @param buffer the buffer to write to <code>MDB_val</code>
118118
* @param size the buffer size to write to <code>MDB_val</code>
119119
* @param ptr the pointer to the <code>MDB_val</code>
120-
* @param ptrAddr the address of the <code>MDB_val</code> pointer
120+
* @return a transient pointer that must be kept alive, or null if none
121121
*/
122-
protectedabstractvoidin(Tbuffer,intsize,Pointerptr,longptrAddr);
122+
protectedabstractPointerin(Tbuffer,intsize,Pointerptr);
123123

124124
/**
125125
* Called when the <code>MDB_val</code> may have changed and the passed buffer should be modified
126126
* to reflect the new <code>MDB_val</code>.
127127
*
128128
* @param buffer the buffer to write to <code>MDB_val</code>
129129
* @param ptr the pointer to the <code>MDB_val</code>
130-
* @param ptrAddr the address of the <code>MDB_val</code> pointer
131130
* @return the buffer for <code>MDB_val</code>
132131
*/
133-
protectedabstractTout(Tbuffer,Pointerptr,longptrAddr);
132+
protectedabstractTout(Tbuffer,Pointerptr);
134133

135134
/**
136135
* Create a new {@link KeyVal} to hold pointers for this buffer proxy.

‎src/main/java/org/lmdbjava/ByteArrayProxy.java‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,20 +114,22 @@ protected Comparator<byte[]> getUnsignedComparator() {
114114
}
115115

116116
@Override
117-
protectedvoidin(finalbyte[]buffer,finalPointerptr,finallongptrAddr) {
117+
protectedPointerin(finalbyte[]buffer,finalPointerptr) {
118118
finalPointerpointer =MEM_MGR.allocateDirect(buffer.length);
119119
pointer.put(0,buffer,0,buffer.length);
120120
ptr.putLong(STRUCT_FIELD_OFFSET_SIZE,buffer.length);
121121
ptr.putAddress(STRUCT_FIELD_OFFSET_DATA,pointer.address());
122+
returnpointer;
122123
}
123124

124125
@Override
125-
protectedvoidin(finalbyte[]buffer,finalintsize,finalPointerptr,finallongptrAddr) {
126+
protectedPointerin(finalbyte[]buffer,finalintsize,finalPointerptr) {
126127
// cannot reserve for byte arrays
128+
returnnull;
127129
}
128130

129131
@Override
130-
protectedbyte[]out(finalbyte[]buffer,finalPointerptr,finallongptrAddr) {
132+
protectedbyte[]out(finalbyte[]buffer,finalPointerptr) {
131133
finallongaddr =ptr.getAddress(STRUCT_FIELD_OFFSET_DATA);
132134
finalintsize = (int)ptr.getLong(STRUCT_FIELD_OFFSET_SIZE);
133135
finalPointerpointer =MEM_MGR.newPointer(addr,size);

‎src/main/java/org/lmdbjava/ByteBufProxy.java‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,26 @@ protected byte[] getBytes(final ByteBuf buffer) {
136136
}
137137

138138
@Override
139-
protectedvoidin(finalByteBufbuffer,finalPointerptr,finallongptrAddr) {
139+
protectedPointerin(finalByteBufbuffer,finalPointerptr) {
140+
finallongptrAddr =ptr.address();
140141
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE,buffer.writerIndex() -buffer.readerIndex());
141142
UNSAFE.putLong(
142143
ptrAddr +STRUCT_FIELD_OFFSET_DATA,buffer.memoryAddress() +buffer.readerIndex());
144+
returnnull;
143145
}
144146

145147
@Override
146-
protectedvoidin(finalByteBufbuffer,finalintsize,finalPointerptr,finallongptrAddr) {
148+
protectedPointerin(finalByteBufbuffer,finalintsize,finalPointerptr) {
149+
finallongptrAddr =ptr.address();
147150
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE,size);
148151
UNSAFE.putLong(
149152
ptrAddr +STRUCT_FIELD_OFFSET_DATA,buffer.memoryAddress() +buffer.readerIndex());
153+
returnnull;
150154
}
151155

152156
@Override
153-
protectedByteBufout(finalByteBufbuffer,finalPointerptr,finallongptrAddr) {
157+
protectedByteBufout(finalByteBufbuffer,finalPointerptr) {
158+
finallongptrAddr =ptr.address();
154159
finallongaddr =UNSAFE.getLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA);
155160
finallongsize =UNSAFE.getLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE);
156161
UNSAFE.putLong(buffer,addressOffset,addr);

‎src/main/java/org/lmdbjava/ByteBufferProxy.java‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,20 +221,22 @@ private static final class ReflectiveProxy extends AbstractByteBufferProxy {
221221
}
222222

223223
@Override
224-
protectedvoidin(finalByteBufferbuffer,finalPointerptr,finallongptrAddr) {
224+
protectedPointerin(finalByteBufferbuffer,finalPointerptr) {
225225
ptr.putAddress(STRUCT_FIELD_OFFSET_DATA,address(buffer));
226226
ptr.putLong(STRUCT_FIELD_OFFSET_SIZE,buffer.remaining());
227+
returnnull;
227228
}
228229

229230
@Override
230-
protectedvoidin(
231-
finalByteBufferbuffer,finalintsize,finalPointerptr,finallongptrAddr) {
231+
protectedPointerin(finalByteBufferbuffer,finalintsize,finalPointerptr) {
232232
ptr.putLong(STRUCT_FIELD_OFFSET_SIZE,size);
233233
ptr.putAddress(STRUCT_FIELD_OFFSET_DATA,address(buffer));
234+
returnnull;
234235
}
235236

236237
@Override
237-
protectedByteBufferout(finalByteBufferbuffer,finalPointerptr,finallongptrAddr) {
238+
protectedByteBufferout(finalByteBufferbuffer,finalPointerptr) {
239+
finallongptrAddr =ptr.address();
238240
finallongaddr =ptr.getAddress(STRUCT_FIELD_OFFSET_DATA);
239241
finallongsize =ptr.getLong(STRUCT_FIELD_OFFSET_SIZE);
240242
try {
@@ -269,20 +271,24 @@ private static final class UnsafeProxy extends AbstractByteBufferProxy {
269271
}
270272

271273
@Override
272-
protectedvoidin(finalByteBufferbuffer,finalPointerptr,finallongptrAddr) {
274+
protectedPointerin(finalByteBufferbuffer,finalPointerptr) {
275+
finallongptrAddr =ptr.address();
273276
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE,buffer.remaining());
274277
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA,address(buffer));
278+
returnnull;
275279
}
276280

277281
@Override
278-
protectedvoidin(
279-
finalByteBufferbuffer,finalintsize,finalPointerptr,finallongptrAddr) {
282+
protectedPointerin(finalByteBufferbuffer,finalintsize,finalPointerptr) {
283+
finallongptrAddr =ptr.address();
280284
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE,size);
281285
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA,address(buffer));
286+
returnnull;
282287
}
283288

284289
@Override
285-
protectedByteBufferout(finalByteBufferbuffer,finalPointerptr,finallongptrAddr) {
290+
protectedByteBufferout(finalByteBufferbuffer,finalPointerptr) {
291+
finallongptrAddr =ptr.address();
286292
finallongaddr =UNSAFE.getLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA);
287293
finallongsize =UNSAFE.getLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE);
288294
UNSAFE.putLong(buffer,ADDRESS_OFFSET,addr);

‎src/main/java/org/lmdbjava/Cursor.java‎

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ public boolean get(final T key, final T data, final SeekOp op) {
141141
checkNotClosed();
142142
txn.checkReady();
143143
}
144-
kv.keyIn(key);
145-
kv.valIn(data);
144+
finalPointertransientKey =kv.keyIn(key);
145+
finalPointertransientVal =kv.valIn(data);
146146

147147
finalintrc =LIB.mdb_cursor_get(ptrCursor,kv.pointerKey(),kv.pointerVal(),op.getCode());
148148

@@ -153,6 +153,10 @@ public boolean get(final T key, final T data, final SeekOp op) {
153153
checkRc(rc);
154154
kv.keyOut();
155155
kv.valOut();
156+
ReferenceUtil.reachabilityFence0(transientKey);
157+
ReferenceUtil.reachabilityFence0(transientVal);
158+
ReferenceUtil.reachabilityFence0(kv.key());
159+
ReferenceUtil.reachabilityFence0(kv.val());
156160
ReferenceUtil.reachabilityFence0(key);
157161
returntrue;
158162
}
@@ -172,7 +176,7 @@ public boolean get(final T key, final GetOp op) {
172176
checkNotClosed();
173177
txn.checkReady();
174178
}
175-
kv.keyIn(key);
179+
finalPointertransientKey =kv.keyIn(key);
176180

177181
finalintrc =LIB.mdb_cursor_get(ptrCursor,kv.pointerKey(),kv.pointerVal(),op.getCode());
178182

@@ -183,6 +187,9 @@ public boolean get(final T key, final GetOp op) {
183187
checkRc(rc);
184188
kv.keyOut();
185189
kv.valOut();
190+
ReferenceUtil.reachabilityFence0(transientKey);
191+
ReferenceUtil.reachabilityFence0(kv.key());
192+
ReferenceUtil.reachabilityFence0(kv.val());
186193
ReferenceUtil.reachabilityFence0(key);
187194
returntrue;
188195
}
@@ -243,8 +250,8 @@ public boolean put(final T key, final T val, final PutFlags... op) {
243250
txn.checkReady();
244251
txn.checkWritesAllowed();
245252
}
246-
kv.keyIn(key);
247-
kv.valIn(val);
253+
finalPointertransientKey =kv.keyIn(key);
254+
finalPointertransientVal =kv.valIn(val);
248255
finalintmask =mask(true,op);
249256
finalintrc =LIB.mdb_cursor_put(ptrCursor,kv.pointerKey(),kv.pointerVal(),mask);
250257
if (rc ==MDB_KEYEXIST) {
@@ -256,6 +263,8 @@ public boolean put(final T key, final T val, final PutFlags... op) {
256263
returnfalse;
257264
}
258265
checkRc(rc);
266+
ReferenceUtil.reachabilityFence0(transientKey);
267+
ReferenceUtil.reachabilityFence0(transientVal);
259268
ReferenceUtil.reachabilityFence0(key);
260269
ReferenceUtil.reachabilityFence0(val);
261270
returntrue;
@@ -287,10 +296,12 @@ public void putMultiple(final T key, final T val, final int elements, final PutF
287296
if (SHOULD_CHECK && !isSet(mask,MDB_MULTIPLE)) {
288297
thrownewIllegalArgumentException("Must set " +MDB_MULTIPLE +" flag");
289298
}
290-
txn.kv().keyIn(key);
299+
finalPointertransientKey =txn.kv().keyIn(key);
291300
finalPointerdataPtr =txn.kv().valInMulti(val,elements);
292301
finalintrc =LIB.mdb_cursor_put(ptrCursor,txn.kv().pointerKey(),dataPtr,mask);
293302
checkRc(rc);
303+
ReferenceUtil.reachabilityFence0(transientKey);
304+
ReferenceUtil.reachabilityFence0(dataPtr);
294305
ReferenceUtil.reachabilityFence0(key);
295306
ReferenceUtil.reachabilityFence0(val);
296307
}
@@ -340,11 +351,13 @@ public T reserve(final T key, final int size, final PutFlags... op) {
340351
txn.checkReady();
341352
txn.checkWritesAllowed();
342353
}
343-
kv.keyIn(key);
344-
kv.valIn(size);
354+
finalPointertransientKey =kv.keyIn(key);
355+
finalPointertransientVal =kv.valIn(size);
345356
finalintflags =mask(true,op) |MDB_RESERVE.getMask();
346357
checkRc(LIB.mdb_cursor_put(ptrCursor,kv.pointerKey(),kv.pointerVal(),flags));
347358
kv.valOut();
359+
ReferenceUtil.reachabilityFence0(transientKey);
360+
ReferenceUtil.reachabilityFence0(transientVal);
348361
ReferenceUtil.reachabilityFence0(key);
349362
returnval();
350363
}

‎src/main/java/org/lmdbjava/Dbi.java‎

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public final class Dbi<T> {
8383
(keyA,keyB) -> {
8484
finalTcompKeyA =proxy.allocate();
8585
finalTcompKeyB =proxy.allocate();
86-
proxy.out(compKeyA,keyA,keyA.address());
87-
proxy.out(compKeyB,keyB,keyB.address());
86+
proxy.out(compKeyA,keyA);
87+
proxy.out(compKeyB,keyB);
8888
finalintresult =this.comparator.compare(compKeyA,compKeyB);
8989
proxy.deallocate(compKeyA);
9090
proxy.deallocate(compKeyB);
@@ -161,18 +161,21 @@ public boolean delete(final Txn<T> txn, final T key, final T val) {
161161
txn.checkWritesAllowed();
162162
}
163163

164-
txn.kv().keyIn(key);
164+
finalPointertransientKey =txn.kv().keyIn(key);
165165

166166
Pointerdata =null;
167+
PointertransientVal =null;
167168
if (val !=null) {
168-
txn.kv().valIn(val);
169+
transientVal =txn.kv().valIn(val);
169170
data =txn.kv().pointerVal();
170171
}
171172
finalintrc =LIB.mdb_del(txn.pointer(),ptr,txn.kv().pointerKey(),data);
172173
if (rc ==MDB_NOTFOUND) {
173174
returnfalse;
174175
}
175176
checkRc(rc);
177+
ReferenceUtil.reachabilityFence0(transientKey);
178+
ReferenceUtil.reachabilityFence0(transientVal);
176179
ReferenceUtil.reachabilityFence0(key);
177180
ReferenceUtil.reachabilityFence0(val);
178181
returntrue;
@@ -232,14 +235,16 @@ public T get(final Txn<T> txn, final T key) {
232235
env.checkNotClosed();
233236
txn.checkReady();
234237
}
235-
txn.kv().keyIn(key);
238+
finalPointertransientKey =txn.kv().keyIn(key);
236239
finalintrc =LIB.mdb_get(txn.pointer(),ptr,txn.kv().pointerKey(),txn.kv().pointerVal());
237240
if (rc ==MDB_NOTFOUND) {
238241
returnnull;
239242
}
240243
checkRc(rc);
244+
finalTresult =txn.kv().valOut();// marked as out in LMDB C docs
245+
ReferenceUtil.reachabilityFence0(transientKey);
241246
ReferenceUtil.reachabilityFence0(key);
242-
returntxn.kv().valOut();// marked as out in LMDB C docs
247+
returnresult;
243248
}
244249

245250
/**
@@ -366,8 +371,8 @@ public boolean put(final Txn<T> txn, final T key, final T val, final PutFlags...
366371
txn.checkReady();
367372
txn.checkWritesAllowed();
368373
}
369-
txn.kv().keyIn(key);
370-
txn.kv().valIn(val);
374+
finalPointertransientKey =txn.kv().keyIn(key);
375+
finalPointertransientVal =txn.kv().valIn(val);
371376
finalintmask =mask(true,flags);
372377
finalintrc =
373378
LIB.mdb_put(txn.pointer(),ptr,txn.kv().pointerKey(),txn.kv().pointerVal(),mask);
@@ -380,6 +385,8 @@ public boolean put(final Txn<T> txn, final T key, final T val, final PutFlags...
380385
returnfalse;
381386
}
382387
checkRc(rc);
388+
ReferenceUtil.reachabilityFence0(transientKey);
389+
ReferenceUtil.reachabilityFence0(transientVal);
383390
ReferenceUtil.reachabilityFence0(key);
384391
ReferenceUtil.reachabilityFence0(val);
385392
returntrue;
@@ -408,11 +415,13 @@ public T reserve(final Txn<T> txn, final T key, final int size, final PutFlags..
408415
txn.checkReady();
409416
txn.checkWritesAllowed();
410417
}
411-
txn.kv().keyIn(key);
412-
txn.kv().valIn(size);
418+
finalPointertransientKey =txn.kv().keyIn(key);
419+
finalPointertransientVal =txn.kv().valIn(size);
413420
finalintflags =mask(true,op) |MDB_RESERVE.getMask();
414421
checkRc(LIB.mdb_put(txn.pointer(),ptr,txn.kv().pointerKey(),txn.kv().pointerVal(),flags));
415422
txn.kv().valOut();// marked as in,out in LMDB C docs
423+
ReferenceUtil.reachabilityFence0(transientKey);
424+
ReferenceUtil.reachabilityFence0(transientVal);
416425
ReferenceUtil.reachabilityFence0(key);
417426
returntxn.val();
418427
}

‎src/main/java/org/lmdbjava/DirectBufferProxy.java‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,23 +134,27 @@ protected byte[] getBytes(final DirectBuffer buffer) {
134134
}
135135

136136
@Override
137-
protectedvoidin(finalDirectBufferbuffer,finalPointerptr,finallongptrAddr) {
137+
protectedPointerin(finalDirectBufferbuffer,finalPointerptr) {
138+
finallongptrAddr =ptr.address();
138139
finallongaddr =buffer.addressOffset();
139140
finallongsize =buffer.capacity();
140141
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA,addr);
141142
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE,size);
143+
returnnull;
142144
}
143145

144146
@Override
145-
protectedvoidin(
146-
finalDirectBufferbuffer,finalintsize,finalPointerptr,finallongptrAddr) {
147+
protectedPointerin(finalDirectBufferbuffer,finalintsize,finalPointerptr) {
148+
finallongptrAddr =ptr.address();
147149
finallongaddr =buffer.addressOffset();
148150
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA,addr);
149151
UNSAFE.putLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE,size);
152+
returnnull;
150153
}
151154

152155
@Override
153-
protectedDirectBufferout(finalDirectBufferbuffer,finalPointerptr,finallongptrAddr) {
156+
protectedDirectBufferout(finalDirectBufferbuffer,finalPointerptr) {
157+
finallongptrAddr =ptr.address();
154158
finallongaddr =UNSAFE.getLong(ptrAddr +STRUCT_FIELD_OFFSET_DATA);
155159
finallongsize =UNSAFE.getLong(ptrAddr +STRUCT_FIELD_OFFSET_SIZE);
156160
buffer.wrap(addr, (int)size);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp