LUCENE-10283: Bump minimum required Java version to 17. (#579)

Co-authored-by: Dawid Weiss <dawid.weiss@carrotsearch.com>
This commit is contained in:
Adrien Grand 2022-01-10 15:42:15 +01:00 committed by GitHub
parent 74698994a9
commit 2ebc57a465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 128 additions and 100 deletions

View File

@ -21,7 +21,7 @@ jobs:
# Operating systems to run on.
os: [ubuntu-latest]
# Test JVMs.
java: [ '11' ]
java: [ '17' ]
steps:
- uses: actions/checkout@v2
@ -65,7 +65,7 @@ jobs:
# macos-latest: a tad slower than ubuntu and pretty much the same (?) so leaving out.
os: [ubuntu-latest]
# Test JVMs.
java: [ '11' ]
java: [ '17' ]
steps:
- uses: actions/checkout@v2

View File

@ -39,16 +39,16 @@ comprehensive documentation, visit:
### Basic steps:
0. Install OpenJDK 11 (or greater).
0. Install OpenJDK 17 (or greater).
1. Clone Lucene's git repository (or download the source distribution).
2. Run gradle launcher script (`gradlew`).
### Step 0) Set up your development environment (OpenJDK 11 or greater)
### Step 0) Set up your development environment (OpenJDK 17 or greater)
We'll assume that you know how to get and set up the JDK - if you
don't, then we suggest starting at https://jdk.java.net/ and learning
more about Java, before returning to this README. Lucene runs with
Java 11 or later.
Java 17 or later.
Lucene uses [Gradle](https://gradle.org/) for build control. Gradle is itself Java-based
and may be incompatible with newer Java versions; you can still build and test

View File

@ -72,7 +72,7 @@ ext {
}
// Minimum Java version required to compile and run Lucene.
minJavaVersion = JavaVersion.VERSION_11
minJavaVersion = JavaVersion.VERSION_17
// snapshot build marker used in scripts.
snapshotBuild = version.contains("SNAPSHOT")

View File

@ -23,7 +23,7 @@ ext {
scriptDepVersions = [
"apache-rat": "0.11",
"commons-codec": "1.13",
"ecj": "3.27.0",
"ecj": "3.28.0",
"flexmark": "0.61.24",
"javacc": "7.0.4",
"jflex": "1.8.2",

View File

@ -37,7 +37,7 @@ configure(project(":lucene").subprojects) { prj ->
lineEndings 'UNIX'
endWithNewline()
googleJavaFormat('1.11.0')
googleJavaFormat('1.13.0')
// Apply to all Java sources
target "src/**/*.java"

View File

@ -32,6 +32,9 @@ Bug Fixes
Other
---------------------
* LUCENE-10283: The minimum required Java version was bumped from 11 to 17.
(Adrien Grand, Uwe Schindler, Dawid Weiss, Robert Muir)
* LUCENE-10253: The @BadApple annotation has been removed from the test
framework. (Adrien Grand)

View File

@ -17,11 +17,11 @@
# System Requirements
Apache Lucene runs on Java 11 or greater.
Apache Lucene runs on Java 17 or greater.
It is also recommended to always use the latest update version of your
Java VM, because bugs may affect Lucene. An overview of known JVM bugs
can be found on http://wiki.apache.org/lucene-java/JavaBugs
can be found on https://cwiki.apache.org/confluence/display/LUCENE/JavaBugs
With all Java versions it is strongly recommended to not use experimental
`-XX` JVM options.

View File

@ -334,8 +334,7 @@ public class MMapDirectory extends FSDirectory {
private static final BufferCleaner CLEANER;
static {
final Object hack =
AccessController.doPrivileged((PrivilegedAction<Object>) MMapDirectory::unmapHackImpl);
final Object hack = doPrivileged(MMapDirectory::unmapHackImpl);
if (hack instanceof BufferCleaner) {
CLEANER = (BufferCleaner) hack;
UNMAP_SUPPORTED = true;
@ -348,6 +347,13 @@ public class MMapDirectory extends FSDirectory {
}
}
// Extracted to a method to be able to apply the SuppressForbidden annotation
@SuppressWarnings("removal")
@SuppressForbidden(reason = "security manager")
private static <T> T doPrivileged(PrivilegedAction<T> action) {
return AccessController.doPrivileged(action);
}
@SuppressForbidden(reason = "Needs access to sun.misc.Unsafe to enable hack")
private static Object unmapHackImpl() {
final Lookup lookup = lookup();
@ -390,16 +396,15 @@ public class MMapDirectory extends FSDirectory {
throw new IllegalArgumentException("unmapping only works with direct buffers");
}
final Throwable error =
AccessController.doPrivileged(
(PrivilegedAction<Throwable>)
() -> {
try {
unmapper.invokeExact(buffer);
return null;
} catch (Throwable t) {
return t;
}
});
doPrivileged(
() -> {
try {
unmapper.invokeExact(buffer);
return null;
} catch (Throwable t) {
return t;
}
});
if (error != null) {
throw new IOException("Unable to unmap the mapped buffer: " + resourceDescription, error);
}

View File

@ -39,8 +39,7 @@ public class NamedThreadFactory implements ThreadFactory {
* @param threadNamePrefix the name prefix assigned to each thread created.
*/
public NamedThreadFactory(String threadNamePrefix) {
final SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
group = getThreadGroup();
this.threadNamePrefix =
String.format(
Locale.ROOT,
@ -49,6 +48,17 @@ public class NamedThreadFactory implements ThreadFactory {
threadPoolNumber.getAndIncrement());
}
@SuppressWarnings("removal")
@SuppressForbidden(reason = "security manager")
private static ThreadGroup getThreadGroup() {
final SecurityManager s = System.getSecurityManager();
if (s != null) {
return s.getThreadGroup();
} else {
return Thread.currentThread().getThreadGroup();
}
}
private static String checkPrefix(String prefix) {
return prefix == null || prefix.length() == 0 ? "Lucene" : prefix;
}

View File

@ -584,9 +584,10 @@ public final class RamUsageEstimator {
final Class<?> target = clazz;
final Field[] fields;
try {
fields =
AccessController.doPrivileged((PrivilegedAction<Field[]>) target::getDeclaredFields);
} catch (AccessControlException e) {
fields = doPrivileged((PrivilegedAction<Field[]>) target::getDeclaredFields);
} catch (
@SuppressWarnings("removal")
AccessControlException e) {
throw new RuntimeException("Can't access fields of class: " + target, e);
}
@ -599,6 +600,13 @@ public final class RamUsageEstimator {
return alignObjectSize(size);
}
// Extracted to a method to give the SuppressForbidden annotation the smallest possible scope
@SuppressWarnings("removal")
@SuppressForbidden(reason = "security manager")
private static <T> T doPrivileged(PrivilegedAction<T> action) {
return AccessController.doPrivileged(action);
}
/** Return shallow size of any <code>array</code>. */
private static long shallowSizeOfArray(Object array) {
long size = NUM_BYTES_ARRAY_HEADER;

View File

@ -20,19 +20,15 @@ import java.io.IOException;
import org.apache.lucene.store.DataInput;
import org.apache.lucene.store.DataOutput;
import org.apache.lucene.util.RamUsageEstimator;
import org.apache.lucene.util.SuppressForbidden;
/**
* An FST {@link Outputs} implementation where each output is a non-negative long value.
*
* @lucene.experimental
*/
@SuppressForbidden(reason = "Uses a Long instance as a marker")
public final class PositiveIntOutputs extends Outputs<Long> {
// Ignore the deprecated constructor. We do want a unique object here.
@SuppressWarnings({"all"})
private static final Long NO_OUTPUT = new Long(0);
private static final Long NO_OUTPUT = 0L;
private static final PositiveIntOutputs singleton = new PositiveIntOutputs();

View File

@ -56,20 +56,14 @@ public class TestCharArraySet extends LuceneTestCase {
@SuppressForbidden(reason = "Explicitly checking new Integers")
public void testObjectContains() {
CharArraySet set = new CharArraySet(10, true);
Integer val = Integer.valueOf(1);
@SuppressWarnings("all")
Integer val1 = new Integer(1);
// Verify explicitly the case of different Integer instances
assertNotSame(val, val1);
Integer val = 1;
set.add(val);
assertTrue(set.contains(val));
assertTrue(set.contains(val1)); // another integer
assertTrue(set.contains("1"));
assertTrue(set.contains(new char[] {'1'}));
// test unmodifiable
set = CharArraySet.unmodifiableSet(set);
assertTrue(set.contains(val));
assertTrue(set.contains(val1)); // another integer
assertTrue(set.contains("1"));
assertTrue(set.contains(new char[] {'1'}));
}

View File

@ -29,6 +29,7 @@ import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.FilterDirectory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.util.SuppressForbidden;
/**
* This directory wrapper overrides {@link Directory#copyFrom(Directory, String, String, IOContext)}
@ -66,27 +67,26 @@ public final class HardlinkCopyDirectoryWrapper extends FilterDirectory {
// only try hardlinks if we have permission to access the files
// if not super.copyFrom() will give us the right exceptions
suppressedException =
AccessController.doPrivileged(
(PrivilegedAction<Exception>)
() -> {
try {
Files.createLink(toPath.resolve(destFile), fromPath.resolve(srcFile));
} catch (FileNotFoundException
| NoSuchFileException
| FileAlreadyExistsException ex) {
return ex; // in these cases we bubble up since it's a true error condition.
} catch (IOException
// if the FS doesn't support hard-links
| UnsupportedOperationException
// we don't have permission to use hard-links just fall back to byte copy
| SecurityException ex) {
// hard-links are not supported or the files are on different filesystems
// we could go deeper and check if their filesstores are the same and opt
// out earlier but for now we just fall back to normal file-copy
return ex;
}
return null;
});
doPrivileged(
() -> {
try {
Files.createLink(toPath.resolve(destFile), fromPath.resolve(srcFile));
} catch (FileNotFoundException
| NoSuchFileException
| FileAlreadyExistsException ex) {
return ex; // in these cases we bubble up since it's a true error condition.
} catch (IOException
// if the FS doesn't support hard-links
| UnsupportedOperationException
// we don't have permission to use hard-links just fall back to byte copy
| SecurityException ex) {
// hard-links are not supported or the files are on different filesystems
// we could go deeper and check if their filesstores are the same and opt
// out earlier but for now we just fall back to normal file-copy
return ex;
}
return null;
});
tryCopy = suppressedException != null;
}
}
@ -101,4 +101,11 @@ public final class HardlinkCopyDirectoryWrapper extends FilterDirectory {
}
}
}
// Extracted to a method to give the SuppressForbidden annotation the smallest possible scope
@SuppressWarnings("removal")
@SuppressForbidden(reason = "security manager")
private static <T> T doPrivileged(PrivilegedAction<T> action) {
return AccessController.doPrivileged(action);
}
}

View File

@ -20,7 +20,6 @@ import java.io.IOException;
import org.apache.lucene.store.DataInput;
import org.apache.lucene.store.DataOutput;
import org.apache.lucene.util.RamUsageEstimator;
import org.apache.lucene.util.SuppressForbidden;
import org.apache.lucene.util.fst.FSTCompiler;
import org.apache.lucene.util.fst.Outputs;
@ -40,7 +39,6 @@ import org.apache.lucene.util.fst.Outputs;
*
* @lucene.experimental
*/
@SuppressForbidden(reason = "Uses a Long instance as a marker")
public final class UpToTwoPositiveIntOutputs extends Outputs<Object> {
/** Holds two long outputs. */
@ -76,9 +74,7 @@ public final class UpToTwoPositiveIntOutputs extends Outputs<Object> {
}
}
// Ignore the deprecated constructor. We do want a unique object here.
@SuppressWarnings({"all"})
private static final Long NO_OUTPUT = new Long(0);
private static final Long NO_OUTPUT = 0L;
private final boolean doShare;

View File

@ -3103,6 +3103,8 @@ public abstract class LuceneTestCase extends Assert {
* execution. If enabled, it needs the following {@link SecurityPermission}: {@code
* "createAccessControlContext"}
*/
@SuppressForbidden(reason = "security manager")
@SuppressWarnings("removal")
public static <T> T runWithRestrictedPermissions(
PrivilegedExceptionAction<T> action, Permission... permissions) throws Exception {
assumeTrue(

View File

@ -323,46 +323,50 @@ public final class RamUsageTester {
/** Create a cached information about shallow size and reference fields for a given class. */
@SuppressForbidden(reason = "We need to access private fields of measured objects.")
private static ClassCache createCacheEntry(final Class<?> clazz) {
return AccessController.doPrivileged(
(PrivilegedAction<ClassCache>)
() -> {
ClassCache cachedInfo;
long shallowInstanceSize = RamUsageEstimator.NUM_BYTES_OBJECT_HEADER;
final ArrayList<Field> referenceFields = new ArrayList<>(32);
for (Class<?> c = clazz; c != null; c = c.getSuperclass()) {
if (c == Class.class) {
// prevent inspection of Class' fields, throws SecurityException in Java 9!
continue;
}
final Field[] fields = c.getDeclaredFields();
for (final Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
shallowInstanceSize = RamUsageEstimator.adjustForField(shallowInstanceSize, f);
@SuppressWarnings("removal")
ClassCache classCache =
AccessController.doPrivileged(
(PrivilegedAction<ClassCache>)
() -> {
ClassCache cachedInfo;
long shallowInstanceSize = RamUsageEstimator.NUM_BYTES_OBJECT_HEADER;
final ArrayList<Field> referenceFields = new ArrayList<>(32);
for (Class<?> c = clazz; c != null; c = c.getSuperclass()) {
if (c == Class.class) {
// prevent inspection of Class' fields, throws SecurityException in Java 9!
continue;
}
final Field[] fields = c.getDeclaredFields();
for (final Field f : fields) {
if (!Modifier.isStatic(f.getModifiers())) {
shallowInstanceSize =
RamUsageEstimator.adjustForField(shallowInstanceSize, f);
if (!f.getType().isPrimitive()) {
try {
f.setAccessible(true);
referenceFields.add(f);
} catch (RuntimeException re) {
throw new RuntimeException(
String.format(
Locale.ROOT,
"Can't access field '%s' of class '%s' for RAM estimation.",
f.getName(),
clazz.getName()),
re);
if (!f.getType().isPrimitive()) {
try {
f.setAccessible(true);
referenceFields.add(f);
} catch (RuntimeException re) {
throw new RuntimeException(
String.format(
Locale.ROOT,
"Can't access field '%s' of class '%s' for RAM estimation.",
f.getName(),
clazz.getName()),
re);
}
}
}
}
}
}
}
cachedInfo =
new ClassCache(
RamUsageEstimator.alignObjectSize(shallowInstanceSize),
referenceFields.toArray(new Field[referenceFields.size()]));
return cachedInfo;
});
cachedInfo =
new ClassCache(
RamUsageEstimator.alignObjectSize(shallowInstanceSize),
referenceFields.toArray(new Field[referenceFields.size()]));
return cachedInfo;
});
return classCache;
}
private static long byteArraySize(int len) {

View File

@ -19,6 +19,7 @@ package org.apache.lucene.tests.util;
import java.lang.StackWalker.StackFrame;
import java.util.Locale;
import java.util.function.Predicate;
import org.apache.lucene.util.SuppressForbidden;
/**
* A {@link SecurityManager} that prevents tests calling {@link System#exit(int)}. Only the test
@ -28,6 +29,8 @@ import java.util.function.Predicate;
* <p>Use this with {@code
* -Djava.security.manager=org.apache.lucene.tests.util.TestSecurityManager}.
*/
@SuppressForbidden(reason = "security manager")
@SuppressWarnings("removal")
public final class TestSecurityManager extends SecurityManager {
private static final String JUNIT4_TEST_RUNNER_PACKAGE = "com.carrotsearch.ant.tasks.junit4.";