Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.virjar.sekiro.business.netty.util.internal.PlatformDependent0 Maven / Gradle / Ivy
/*
* Copyright 2013 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:
*
* http://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 com.virjar.sekiro.business.netty.util.internal;
import com.virjar.sekiro.business.netty.util.internal.logging.InternalLogger;
import com.virjar.sekiro.business.netty.util.internal.logging.InternalLoggerFactory;
import sun.misc.Unsafe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import static com.virjar.sekiro.business.netty.util.internal.ObjectUtil.checkNotNull;
/**
* The {@link PlatformDependent} operations which requires access to {@code sun.misc.*}.
*/
final class PlatformDependent0 {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent0.class);
static final Unsafe UNSAFE;
private static final long ADDRESS_FIELD_OFFSET;
private static final long BYTE_ARRAY_BASE_OFFSET;
private static final Constructor> DIRECT_BUFFER_CONSTRUCTOR;
/**
* Limits the number of bytes to copy per {@link Unsafe#copyMemory(long, long, long)} to allow safepoint polling
* during a large copy.
*/
private static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
private static final boolean UNALIGNED;
static {
final ByteBuffer direct;
final Field addressField;
if (PlatformDependent.isExplicitNoUnsafe()) {
direct = null;
addressField = null;
} else {
direct = ByteBuffer.allocateDirect(1);
// attempt to access field Buffer#address
final Object maybeAddressField = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
try {
final Field field = Buffer.class.getDeclaredField("address");
field.setAccessible(true);
// if direct really is a direct buffer, address will be non-zero
if (field.getLong(direct) == 0) {
return null;
}
return field;
} catch (IllegalAccessException e) {
return e;
} catch (NoSuchFieldException e) {
return e;
} catch (SecurityException e) {
return e;
}
}
});
if (maybeAddressField instanceof Field) {
addressField = (Field) maybeAddressField;
logger.debug("java.nio.Buffer.address: available");
} else {
logger.debug("java.nio.Buffer.address: unavailable", (Throwable) maybeAddressField);
addressField = null;
}
}
Unsafe unsafe;
if (addressField != null) {
// attempt to access field Unsafe#theUnsafe
final Object maybeUnsafe = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
try {
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
// the unsafe instance
return unsafeField.get(null);
} catch (NoSuchFieldException e) {
return e;
} catch (SecurityException e) {
return e;
} catch (IllegalAccessException e) {
return e;
}
}
});
// the conditional check here can not be replaced with checking that maybeUnsafe
// is an instanceof Unsafe and reversing the if and else blocks; this is because an
// instanceof check against Unsafe will trigger a class load and we might not have
// the runtime permission accessClassInPackage.sun.misc
if (maybeUnsafe instanceof Exception) {
unsafe = null;
logger.debug("sun.misc.Unsafe.theUnsafe: unavailable", (Exception) maybeUnsafe);
} else {
unsafe = (Unsafe) maybeUnsafe;
logger.debug("sun.misc.Unsafe.theUnsafe: available");
}
// ensure the unsafe supports all necessary methods to work around the mistake in the latest OpenJDK
// https://github.com/netty/netty/issues/1061
// http://www.mail-archive.com/[email protected] /msg00698.html
if (unsafe != null) {
final Unsafe finalUnsafe = unsafe;
final Object maybeException = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
try {
finalUnsafe.getClass().getDeclaredMethod(
"copyMemory", Object.class, long.class, Object.class, long.class, long.class);
return null;
} catch (NoSuchMethodException e) {
return e;
} catch (SecurityException e) {
return e;
}
}
});
if (maybeException == null) {
logger.debug("sun.misc.Unsafe.copyMemory: available");
} else {
// Unsafe.copyMemory(Object, long, Object, long, long) unavailable.
unsafe = null;
logger.debug("sun.misc.Unsafe.copyMemory: unavailable", (Throwable) maybeException);
}
}
} else {
// If we cannot access the address of a direct buffer, there's no point of using unsafe.
// Let's just pretend unsafe is unavailable for overall simplicity.
unsafe = null;
}
UNSAFE = unsafe;
if (unsafe == null) {
BYTE_ARRAY_BASE_OFFSET = -1;
ADDRESS_FIELD_OFFSET = -1;
UNALIGNED = false;
DIRECT_BUFFER_CONSTRUCTOR = null;
} else {
Constructor> directBufferConstructor;
long address = -1;
try {
final Object maybeDirectBufferConstructor =
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
try {
final Constructor> constructor =
direct.getClass().getDeclaredConstructor(long.class, int.class);
constructor.setAccessible(true);
return constructor;
} catch (NoSuchMethodException e) {
return e;
} catch (SecurityException e) {
return e;
}
}
});
if (maybeDirectBufferConstructor instanceof Constructor>) {
address = UNSAFE.allocateMemory(1);
// try to use the constructor now
try {
((Constructor>) maybeDirectBufferConstructor).newInstance(address, 1);
directBufferConstructor = (Constructor>) maybeDirectBufferConstructor;
logger.debug("direct buffer constructor: available");
} catch (InstantiationException e) {
directBufferConstructor = null;
} catch (IllegalAccessException e) {
directBufferConstructor = null;
} catch (InvocationTargetException e) {
directBufferConstructor = null;
}
} else {
logger.debug(
"direct buffer constructor: unavailable",
(Throwable) maybeDirectBufferConstructor);
directBufferConstructor = null;
}
} finally {
if (address != -1) {
UNSAFE.freeMemory(address);
}
}
DIRECT_BUFFER_CONSTRUCTOR = directBufferConstructor;
ADDRESS_FIELD_OFFSET = objectFieldOffset(addressField);
boolean unaligned;
Object maybeUnaligned = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
try {
Class> bitsClass =
Class.forName("java.nio.Bits", false, PlatformDependent.getSystemClassLoader());
Method unalignedMethod = bitsClass.getDeclaredMethod("unaligned");
unalignedMethod.setAccessible(true);
return unalignedMethod.invoke(null);
} catch (Throwable cause) {
return cause;
}
}
});
if (maybeUnaligned instanceof Boolean) {
unaligned = (Boolean) maybeUnaligned;
logger.debug("java.nio.Bits.unaligned: available, {}", unaligned);
} else {
String arch = SystemPropertyUtil.get("os.arch", "");
//noinspection DynamicRegexReplaceableByCompiledPattern
unaligned = arch.matches("^(i[3-6]86|x86(_64)?|x64|amd64)$");
Throwable t = (Throwable) maybeUnaligned;
logger.debug("java.nio.Bits.unaligned: unavailable {}", unaligned, t);
}
UNALIGNED = unaligned;
BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset();
}
logger.debug("java.nio.DirectByteBuffer.(long, int): {}",
DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable");
if (direct != null) {
freeDirectBuffer(direct);
}
}
static boolean isUnaligned() {
return UNALIGNED;
}
static boolean hasUnsafe() {
return UNSAFE != null;
}
static void throwException(Throwable cause) {
// JVM has been observed to crash when passing a null argument. See https://github.com/netty/netty/issues/4131.
UNSAFE.throwException(checkNotNull(cause, "cause"));
}
static boolean hasDirectBufferNoCleanerConstructor() {
return DIRECT_BUFFER_CONSTRUCTOR != null;
}
static ByteBuffer reallocateDirectNoCleaner(ByteBuffer buffer, int capacity) {
return newDirectBuffer(UNSAFE.reallocateMemory(directBufferAddress(buffer), capacity), capacity);
}
static ByteBuffer allocateDirectNoCleaner(int capacity) {
return newDirectBuffer(UNSAFE.allocateMemory(capacity), capacity);
}
static ByteBuffer newDirectBuffer(long address, int capacity) {
ObjectUtil.checkPositiveOrZero(address, "address");
ObjectUtil.checkPositiveOrZero(capacity, "capacity");
try {
return (ByteBuffer) DIRECT_BUFFER_CONSTRUCTOR.newInstance(address, capacity);
} catch (Throwable cause) {
// Not expected to ever throw!
if (cause instanceof Error) {
throw (Error) cause;
}
throw new Error(cause);
}
}
static void freeDirectBuffer(ByteBuffer buffer) {
// Delegate to other class to not break on android
// See https://github.com/netty/netty/issues/2604
Cleaner0.freeDirectBuffer(buffer);
}
static long directBufferAddress(ByteBuffer buffer) {
return getLong(buffer, ADDRESS_FIELD_OFFSET);
}
static long arrayBaseOffset() {
return UNSAFE.arrayBaseOffset(byte[].class);
}
static Object getObject(Object object, long fieldOffset) {
return UNSAFE.getObject(object, fieldOffset);
}
static Object getObjectVolatile(Object object, long fieldOffset) {
return UNSAFE.getObjectVolatile(object, fieldOffset);
}
static int getInt(Object object, long fieldOffset) {
return UNSAFE.getInt(object, fieldOffset);
}
private static long getLong(Object object, long fieldOffset) {
return UNSAFE.getLong(object, fieldOffset);
}
static long objectFieldOffset(Field field) {
return UNSAFE.objectFieldOffset(field);
}
static byte getByte(long address) {
return UNSAFE.getByte(address);
}
static short getShort(long address) {
return UNSAFE.getShort(address);
}
static int getInt(long address) {
return UNSAFE.getInt(address);
}
static long getLong(long address) {
return UNSAFE.getLong(address);
}
static byte getByte(byte[] data, int index) {
return UNSAFE.getByte(data, BYTE_ARRAY_BASE_OFFSET + index);
}
static short getShort(byte[] data, int index) {
return UNSAFE.getShort(data, BYTE_ARRAY_BASE_OFFSET + index);
}
static int getInt(byte[] data, int index) {
return UNSAFE.getInt(data, BYTE_ARRAY_BASE_OFFSET + index);
}
static long getLong(byte[] data, int index) {
return UNSAFE.getLong(data, BYTE_ARRAY_BASE_OFFSET + index);
}
static void putByte(long address, byte value) {
UNSAFE.putByte(address, value);
}
static void putShort(long address, short value) {
UNSAFE.putShort(address, value);
}
static void putInt(long address, int value) {
UNSAFE.putInt(address, value);
}
static void putLong(long address, long value) {
UNSAFE.putLong(address, value);
}
static void putByte(byte[] data, int index, byte value) {
UNSAFE.putByte(data, BYTE_ARRAY_BASE_OFFSET + index, value);
}
static void putShort(byte[] data, int index, short value) {
UNSAFE.putShort(data, BYTE_ARRAY_BASE_OFFSET + index, value);
}
static void putInt(byte[] data, int index, int value) {
UNSAFE.putInt(data, BYTE_ARRAY_BASE_OFFSET + index, value);
}
static void putLong(byte[] data, int index, long value) {
UNSAFE.putLong(data, BYTE_ARRAY_BASE_OFFSET + index, value);
}
static void copyMemory(long srcAddr, long dstAddr, long length) {
//UNSAFE.copyMemory(srcAddr, dstAddr, length);
while (length > 0) {
long size = Math.min(length, UNSAFE_COPY_THRESHOLD);
UNSAFE.copyMemory(srcAddr, dstAddr, size);
length -= size;
srcAddr += size;
dstAddr += size;
}
}
static void copyMemory(Object src, long srcOffset, Object dst, long dstOffset, long length) {
//UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, length);
while (length > 0) {
long size = Math.min(length, UNSAFE_COPY_THRESHOLD);
UNSAFE.copyMemory(src, srcOffset, dst, dstOffset, size);
length -= size;
srcOffset += size;
dstOffset += size;
}
}
static void setMemory(long address, long bytes, byte value) {
UNSAFE.setMemory(address, bytes, value);
}
static void setMemory(Object o, long offset, long bytes, byte value) {
UNSAFE.setMemory(o, offset, bytes, value);
}
static ClassLoader getClassLoader(final Class> clazz) {
if (System.getSecurityManager() == null) {
return clazz.getClassLoader();
} else {
return AccessController.doPrivileged(new PrivilegedAction() {
@Override
public ClassLoader run() {
return clazz.getClassLoader();
}
});
}
}
static ClassLoader getContextClassLoader() {
if (System.getSecurityManager() == null) {
return Thread.currentThread().getContextClassLoader();
} else {
return AccessController.doPrivileged(new PrivilegedAction() {
@Override
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
}
}
static ClassLoader getSystemClassLoader() {
if (System.getSecurityManager() == null) {
return ClassLoader.getSystemClassLoader();
} else {
return AccessController.doPrivileged(new PrivilegedAction() {
@Override
public ClassLoader run() {
return ClassLoader.getSystemClassLoader();
}
});
}
}
static int addressSize() {
return UNSAFE.addressSize();
}
static long allocateMemory(long size) {
return UNSAFE.allocateMemory(size);
}
static void freeMemory(long address) {
UNSAFE.freeMemory(address);
}
private PlatformDependent0() {
}
}