mirror of https://github.com/apache/lucene.git
LUCENE-10283: Bump minimum required Java version to 17. (#579)
Co-authored-by: Dawid Weiss <dawid.weiss@carrotsearch.com>
This commit is contained in:
parent
74698994a9
commit
2ebc57a465
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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'}));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.";
|
||||
|
|
Loading…
Reference in New Issue