Skip to content

Commit

Permalink
move to JDK17 (graphhopper#2827)
Browse files Browse the repository at this point in the history
* move to JDK17

* Update pom.xml

Co-authored-by: otbutz <tbutz@optitool.de>

* simplify cleanMappedByteBuffer

---------

Co-authored-by: otbutz <tbutz@optitool.de>
  • Loading branch information
karussell and otbutz authored Oct 18, 2023
1 parent aa2ffd4 commit c721fa3
Show file tree
Hide file tree
Showing 9 changed files with 20 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish-maven-central.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
java-version: 8
java-version: 17
distribution: temurin
server-id: ossrh
server-username: MAVEN_USERNAME
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ To get started you can try [GraphHopper Maps](README.md#graphhopper-maps), read

## Installation

To install the [GraphHopper Maps](https://graphhopper.com/maps/) UI and the web service locally you [need a JVM](https://adoptium.net) (>= Java 8) and do:
To install the [GraphHopper Maps](https://graphhopper.com/maps/) UI and the web service locally you [need a JVM](https://adoptium.net) (>= Java 17) and do:

```bash
wget https://repo1.maven.org/maven2/com/graphhopper/graphhopper-web/8.0/graphhopper-web-8.0.jar https://raw.githubusercontent.com/graphhopper/graphhopper/8.x/config-example.yml http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf
Expand Down
90 changes: 13 additions & 77 deletions core/src/main/java/com/graphhopper/storage/MMapDataAccess.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package com.graphhopper.storage;

import com.graphhopper.util.Constants;
import com.graphhopper.util.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -56,8 +55,6 @@
*/
public final class MMapDataAccess extends AbstractDataAccess {

private static final Logger LOGGER = LoggerFactory.getLogger(MMapDataAccess.class);

private final boolean allowWrites;
private RandomAccessFile raFile;
private final List<MappedByteBuffer> segments = new ArrayList<>();
Expand All @@ -67,96 +64,35 @@ public final class MMapDataAccess extends AbstractDataAccess {
this.allowWrites = allowWrites;
}

public static boolean jreIsMinimumJava9() {
final StringTokenizer st = new StringTokenizer(System.getProperty("java.specification.version"), ".");
int JVM_MAJOR_VERSION = Integer.parseInt(st.nextToken());
int JVM_MINOR_VERSION;
if (st.hasMoreTokens()) {
JVM_MINOR_VERSION = Integer.parseInt(st.nextToken());
} else {
JVM_MINOR_VERSION = 0;
}
return JVM_MAJOR_VERSION > 1 || (JVM_MAJOR_VERSION == 1 && JVM_MINOR_VERSION >= 9);
}

public static void cleanMappedByteBuffer(final ByteBuffer buffer) {
// TODO avoid reflection on every call
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
if (jreIsMinimumJava9()) {
// >=JDK9 class sun.misc.Unsafe { void invokeCleaner(ByteBuffer buf) }
final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
// fetch the unsafe instance and bind it to the virtual MethodHandle
final Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
final Object theUnsafe = f.get(null);
final Method method = unsafeClass.getDeclaredMethod("invokeCleaner", ByteBuffer.class);
try {
method.invoke(theUnsafe, buffer);
return null;
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

if (buffer.getClass().getSimpleName().equals("MappedByteBufferAdapter")) {
if (!Constants.ANDROID)
throw new RuntimeException("MappedByteBufferAdapter only supported for Android at the moment");

// For Android 4.1 call ((MappedByteBufferAdapter)buffer).free() see #914
Class<?> directByteBufferClass = Class.forName("java.nio.MappedByteBufferAdapter");
callBufferFree(buffer, directByteBufferClass);
} else {
// <=JDK8 class DirectByteBuffer { sun.misc.Cleaner cleaner(Buffer buf) }
// then call sun.misc.Cleaner.clean
final Class<?> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
try {
final Method dbbCleanerMethod = directByteBufferClass.getMethod("cleaner");
dbbCleanerMethod.setAccessible(true);
// call: cleaner = ((DirectByteBuffer)buffer).cleaner()
final Object cleaner = dbbCleanerMethod.invoke(buffer);
if (cleaner != null) {
final Class<?> cleanerMethodReturnType = dbbCleanerMethod.getReturnType();
final Method cleanMethod = cleanerMethodReturnType.getDeclaredMethod("clean");
cleanMethod.setAccessible(true);
// call: ((sun.misc.Cleaner)cleaner).clean()
cleanMethod.invoke(cleaner);
}
} catch (NoSuchMethodException ex2) {
if (Constants.ANDROID)
// For Android 5.1.1 call ((DirectByteBuffer)buffer).free() see #933
callBufferFree(buffer, directByteBufferClass);
else
// ignore if method cleaner or clean is not available
LOGGER.warn("NoSuchMethodException | " + System.getProperty("java.version"), ex2);
}
// >=JDK9 class sun.misc.Unsafe { void invokeCleaner(ByteBuffer buf) }
final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
// fetch the unsafe instance and bind it to the virtual MethodHandle
final Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
final Object theUnsafe = f.get(null);
final Method method = unsafeClass.getDeclaredMethod("invokeCleaner", ByteBuffer.class);
try {
method.invoke(theUnsafe, buffer);
return null;
} catch (Throwable t) {
throw new RuntimeException(t);
}

return null;
}
});
} catch (PrivilegedActionException e) {
throw new RuntimeException("Unable to unmap the mapped buffer", e);
}
}

private static void callBufferFree(ByteBuffer buffer, Class<?> directByteBufferClass)
throws InvocationTargetException, IllegalAccessException {
try {
final Method dbbFreeMethod = directByteBufferClass.getMethod("free");
dbbFreeMethod.setAccessible(true);
dbbFreeMethod.invoke(buffer);
} catch (NoSuchMethodException ex2) {
LOGGER.warn("NoSuchMethodException | " + System.getProperty("java.version"), ex2);
}
}

private void initRandomAccessFile() {
if (raFile != null) {
if (raFile != null)
return;
}

try {
// raFile necessary for loadExisting and create
Expand Down
8 changes: 0 additions & 8 deletions core/src/main/java/com/graphhopper/util/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,10 @@ public class Constants {
* True iff running on Linux.
*/
public static final boolean LINUX = OS_NAME.startsWith("Linux");
/**
* True iff running on Android.
*/
public static final boolean ANDROID = System.getProperty("java.vendor").contains("Android");
/**
* True iff running on Windows.
*/
public static final boolean WINDOWS = OS_NAME.startsWith("Windows");
/**
* True iff running on SunOS.
*/
public static final boolean SUN_OS = OS_NAME.startsWith("SunOS");
/**
* True iff running on Mac OS X
*/
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/com/graphhopper/util/GitInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ public boolean isDirty() {
}

public String toString() {
return Helper.join("|", Arrays.asList(commitHash, branch, "dirty=" + dirty, commitTime, commitMessage));
return String.join("|", Arrays.asList(commitHash, branch, "dirty=" + dirty, commitTime, commitMessage));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public void testRandomGraph(String algoStr) {
}
if (strictViolations.size() > 0.05 * numQueries) {
fail("Too many strict violations: " + strictViolations.size() + "/" + numQueries + "\n" +
Helper.join("\n", strictViolations));
String.join("\n", strictViolations));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ private void runRandomTest(Fixture f, Random rnd) {
}
if (strictViolations.size() > 0.05 * numQueries) {
fail("Too many strict violations: " + strictViolations.size() + "/" + numQueries + "\n" +
Helper.join("\n", strictViolations));
String.join("\n", strictViolations));
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.target>17</maven.compiler.target>

<!-- We always had this disabled as it is disabled by default in debian JDK builds, but when we
switched to another JDK on travis it was enabled implicitly. Our javadocs are not ready for this
Expand Down Expand Up @@ -183,8 +183,7 @@
<compilerArgument>-Xlint:deprecation</compilerArgument>
-->
<fork>true</fork>
<source>1.8</source>
<target>1.8</target>
<release>17</release>
</configuration>
</plugin>

Expand Down
14 changes: 0 additions & 14 deletions web-api/src/main/java/com/graphhopper/util/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,20 +413,6 @@ public static String underScoreToCamelCase(String key) {
return sb.toString();
}

/**
* Equivalent to java 8 String#join
*/
public static String join(String delimiter, List<String> strings) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < strings.size(); i++) {
if (i > 0) {
sb.append(delimiter);
}
sb.append(strings.get(i));
}
return sb.toString();
}

/**
* parses a string like [a,b,c]
*/
Expand Down

0 comments on commit c721fa3

Please sign in to comment.