Remove CleanerJava6 (#10746)
Motivation: Netty 5 will require Java 11 at a minimum, so this pre-Java 9 specific code will never be used. Modification: Removed the dead code. Result: Less code to maintain.
This commit is contained in:
parent
38adfd8316
commit
d804e34cf0
@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014 The Netty Project
|
|
||||||
*
|
|
||||||
* The Netty Project licenses this file to you under the Apache License,
|
|
||||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package io.netty.util.internal;
|
|
||||||
|
|
||||||
import io.netty.util.internal.logging.InternalLogger;
|
|
||||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.MethodType;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows to free direct {@link ByteBuffer} by using Cleaner. This is encapsulated in an extra class to be able
|
|
||||||
* to use {@link PlatformDependent0} on Android without problems.
|
|
||||||
*
|
|
||||||
* For more details see <a href="https://github.com/netty/netty/issues/2604">#2604</a>.
|
|
||||||
*/
|
|
||||||
final class CleanerJava6 implements Cleaner {
|
|
||||||
private static final long CLEANER_FIELD_OFFSET;
|
|
||||||
private static final MethodHandle CLEAN_HANDLE;
|
|
||||||
private static final MethodHandle CLEANER_FIELD_HANDLE;
|
|
||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(CleanerJava6.class);
|
|
||||||
|
|
||||||
static {
|
|
||||||
long fieldOffset;
|
|
||||||
MethodHandle cleanHandle = null;
|
|
||||||
MethodHandle cleanerFieldHandle = null;
|
|
||||||
Throwable error = null;
|
|
||||||
final ByteBuffer direct = ByteBuffer.allocateDirect(1);
|
|
||||||
try {
|
|
||||||
Object mayBeCleanerField = AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
|
||||||
try {
|
|
||||||
Field cleanerField1 = direct.getClass().getDeclaredField("cleaner");
|
|
||||||
if (!PlatformDependent.hasUnsafe()) {
|
|
||||||
// We need to make it accessible if we do not use Unsafe as we will access it via
|
|
||||||
// reflection.
|
|
||||||
cleanerField1.setAccessible(true);
|
|
||||||
}
|
|
||||||
return cleanerField1;
|
|
||||||
} catch (Throwable cause) {
|
|
||||||
return cause;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (mayBeCleanerField instanceof Throwable) {
|
|
||||||
throw (Throwable) mayBeCleanerField;
|
|
||||||
}
|
|
||||||
|
|
||||||
Field cleanerField = (Field) mayBeCleanerField;
|
|
||||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
|
||||||
|
|
||||||
final Object cleaner;
|
|
||||||
|
|
||||||
// If we have sun.misc.Unsafe we will use it as its faster then using reflection,
|
|
||||||
// otherwise let us try reflection as last resort.
|
|
||||||
if (PlatformDependent.hasUnsafe()) {
|
|
||||||
fieldOffset = PlatformDependent0.objectFieldOffset(cleanerField);
|
|
||||||
cleaner = PlatformDependent0.getObject(direct, fieldOffset);
|
|
||||||
} else {
|
|
||||||
fieldOffset = -1;
|
|
||||||
cleaner = cleanerField.get(direct);
|
|
||||||
cleanerFieldHandle = lookup.unreflectGetter(cleanerField);
|
|
||||||
}
|
|
||||||
cleanHandle = lookup.findVirtual(cleaner.getClass(), "clean", MethodType.methodType(void.class));
|
|
||||||
cleanHandle.invoke(cleaner);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
// We don't have ByteBuffer.cleaner().
|
|
||||||
fieldOffset = -1;
|
|
||||||
cleanerFieldHandle = null;
|
|
||||||
cleanHandle = null;
|
|
||||||
error = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == null) {
|
|
||||||
logger.debug("java.nio.ByteBuffer.cleaner(): available");
|
|
||||||
} else {
|
|
||||||
logger.debug("java.nio.ByteBuffer.cleaner(): unavailable", error);
|
|
||||||
}
|
|
||||||
CLEANER_FIELD_HANDLE = cleanerFieldHandle;
|
|
||||||
CLEANER_FIELD_OFFSET = fieldOffset;
|
|
||||||
CLEAN_HANDLE = cleanHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isSupported() {
|
|
||||||
return CLEANER_FIELD_OFFSET != -1 || CLEANER_FIELD_HANDLE != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void freeDirectBuffer(ByteBuffer buffer) {
|
|
||||||
if (!buffer.isDirect()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (System.getSecurityManager() == null) {
|
|
||||||
try {
|
|
||||||
freeDirectBuffer0(buffer);
|
|
||||||
} catch (Throwable cause) {
|
|
||||||
PlatformDependent.throwException(cause);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
freeDirectBufferPrivileged(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void freeDirectBufferPrivileged(final ByteBuffer buffer) {
|
|
||||||
Throwable cause = AccessController.doPrivileged((PrivilegedAction<Throwable>) () -> {
|
|
||||||
try {
|
|
||||||
freeDirectBuffer0(buffer);
|
|
||||||
return null;
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
return throwable;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (cause != null) {
|
|
||||||
PlatformDependent.throwException(cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void freeDirectBuffer0(ByteBuffer buffer) throws Throwable {
|
|
||||||
final Object cleaner;
|
|
||||||
// If CLEANER_FIELD_OFFSET == -1 we need to use reflection to access the cleaner, otherwise we can use
|
|
||||||
// sun.misc.Unsafe.
|
|
||||||
if (CLEANER_FIELD_OFFSET == -1) {
|
|
||||||
cleaner = CLEANER_FIELD_HANDLE.invoke(buffer);
|
|
||||||
} else {
|
|
||||||
cleaner = PlatformDependent0.getObject(buffer, CLEANER_FIELD_OFFSET);
|
|
||||||
}
|
|
||||||
if (cleaner != null) {
|
|
||||||
CLEAN_HANDLE.invoke(cleaner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -162,11 +162,7 @@ public final class PlatformDependent {
|
|||||||
if (!isAndroid()) {
|
if (!isAndroid()) {
|
||||||
// only direct to method if we are not running on android.
|
// only direct to method if we are not running on android.
|
||||||
// See https://github.com/netty/netty/issues/2604
|
// See https://github.com/netty/netty/issues/2604
|
||||||
if (javaVersion() >= 9) {
|
CLEANER = CleanerJava9.isSupported() ? new CleanerJava9() : NOOP;
|
||||||
CLEANER = CleanerJava9.isSupported() ? new CleanerJava9() : NOOP;
|
|
||||||
} else {
|
|
||||||
CLEANER = CleanerJava6.isSupported() ? new CleanerJava6() : NOOP;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
CLEANER = NOOP;
|
CLEANER = NOOP;
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 The Netty Project
|
|
||||||
*
|
|
||||||
* The Netty Project licenses this file to you under the Apache License,
|
|
||||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package io.netty.util.internal.svm;
|
|
||||||
|
|
||||||
import com.oracle.svm.core.annotate.Alias;
|
|
||||||
import com.oracle.svm.core.annotate.RecomputeFieldValue;
|
|
||||||
import com.oracle.svm.core.annotate.TargetClass;
|
|
||||||
|
|
||||||
@TargetClass(className = "io.netty.util.internal.CleanerJava6")
|
|
||||||
final class CleanerJava6Substitution {
|
|
||||||
private CleanerJava6Substitution() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Alias
|
|
||||||
@RecomputeFieldValue(
|
|
||||||
kind = RecomputeFieldValue.Kind.FieldOffset,
|
|
||||||
declClassName = "java.nio.DirectByteBuffer",
|
|
||||||
name = "cleaner")
|
|
||||||
private static long CLEANER_FIELD_OFFSET;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user