Skip to content

Commit 8ef1e64

Browse files
committed
under Android 5.x calling DirectByteBuffer.free is necessary, graphhopper#933
1 parent 24398fa commit 8ef1e64

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

core/src/main/java/com/graphhopper/util/Helper.java

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.lang.invoke.MethodHandles;
2929
import java.lang.invoke.MethodType;
3030
import java.lang.reflect.Field;
31+
import java.lang.reflect.InvocationTargetException;
3132
import java.lang.reflect.Method;
3233
import java.nio.ByteBuffer;
3334
import java.nio.MappedByteBuffer;
@@ -388,21 +389,18 @@ public Object run() throws Exception {
388389
}
389390
}
390391

391-
// <=JDK8 class DirectByteBuffer { sun.misc.Cleaner cleaner(Buffer buf) }
392-
// then call sun.misc.Cleaner.clean
393-
try {
394-
if (buffer.getClass().getSimpleName().equals("MappedByteBufferAdapter")) {
395-
if (!Constants.ANDROID)
396-
throw new RuntimeException("MappedByteBufferAdapter only supported for Android at the moment");
397-
398-
// Regarding MappedByteBufferAdapter on Android 4.1, see #914
399-
final Class<?> directByteBufferClass = Class.forName("java.nio.MappedByteBufferAdapter");
400-
final Method dbbFreeMethod = directByteBufferClass.getMethod("free");
401-
dbbFreeMethod.setAccessible(true);
402-
// call: ((MappedByteBufferAdapter)buffer).free()
403-
dbbFreeMethod.invoke(buffer);
404-
} else {
405-
final Class<?> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
392+
if (buffer.getClass().getSimpleName().equals("MappedByteBufferAdapter")) {
393+
if (!Constants.ANDROID)
394+
throw new RuntimeException("MappedByteBufferAdapter only supported for Android at the moment");
395+
396+
// For Android 4.1 call ((MappedByteBufferAdapter)buffer).free() see #914
397+
Class<?> directByteBufferClass = Class.forName("java.nio.MappedByteBufferAdapter");
398+
callBufferFree(buffer, directByteBufferClass);
399+
} else {
400+
// <=JDK8 class DirectByteBuffer { sun.misc.Cleaner cleaner(Buffer buf) }
401+
// then call sun.misc.Cleaner.clean
402+
final Class<?> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
403+
try {
406404
final Method dbbCleanerMethod = directByteBufferClass.getMethod("cleaner");
407405
dbbCleanerMethod.setAccessible(true);
408406
// call: cleaner = ((DirectByteBuffer)buffer).cleaner()
@@ -414,11 +412,16 @@ public Object run() throws Exception {
414412
// call: ((sun.misc.Cleaner)cleaner).clean()
415413
cleanMethod.invoke(cleaner);
416414
}
415+
} catch (NoSuchMethodException ex2) {
416+
if (Constants.ANDROID)
417+
// For Android 5.1.1 call ((DirectByteBuffer)buffer).free() see #933
418+
callBufferFree(buffer, directByteBufferClass);
419+
else
420+
// ignore if method cleaner or clean is not available
421+
LOGGER.warn("NoSuchMethodException | " + Constants.JAVA_VERSION, ex2);
417422
}
418-
} catch (NoSuchMethodException ex2) {
419-
// ignore if method cleaner or clean is not available
420-
LOGGER.warn("NoSuchMethodException | " + Constants.JAVA_VERSION, ex2);
421423
}
424+
422425
return null;
423426
}
424427
});
@@ -427,6 +430,17 @@ public Object run() throws Exception {
427430
}
428431
}
429432

433+
private static void callBufferFree(ByteBuffer buffer, Class<?> directByteBufferClass)
434+
throws InvocationTargetException, IllegalAccessException {
435+
try {
436+
final Method dbbFreeMethod = directByteBufferClass.getMethod("free");
437+
dbbFreeMethod.setAccessible(true);
438+
dbbFreeMethod.invoke(buffer);
439+
} catch (NoSuchMethodException ex2) {
440+
LOGGER.warn("NoSuchMethodException | " + Constants.JAVA_VERSION, ex2);
441+
}
442+
}
443+
430444
/**
431445
* Trying to force the release of the mapped ByteBuffer. See
432446
* http://stackoverflow.com/q/2972986/194609 and use only if you know what you are doing.

0 commit comments

Comments
 (0)