All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.nio.UnsafeHelper Maven / Gradle / Ivy

There is a newer version: 4.5.4
Show newest version
/*
 * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed 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.hazelcast.nio;

import com.hazelcast.internal.memory.GlobalMemoryAccessorRegistry;
import com.hazelcast.internal.memory.MemoryAccessor;
import com.hazelcast.internal.memory.impl.AlignmentUtil;
import com.hazelcast.logging.Logger;
import com.hazelcast.spi.annotation.PrivateApi;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;

import static com.hazelcast.util.QuickMath.normalize;

/**
 * Unsafe accessor.
 * 

* Warning: Although both array base-offsets and array index-scales are constant over time currently, * a later JVM implementation can change this behaviour to allow varying index-scales and base-offsets * over time or per array instances (e.g. compressed primitive arrays or backwards growing arrays...) *

*

* See Gil Tene's comment related to Unsafe usage; * https://groups.google.com/d/msg/mechanical-sympathy/X-GtLuG0ETo/LMV1d_2IybQJ *

* @deprecated Use {@link MemoryAccessor} instead due to following reasons: *

* Deprecated to {@link MemoryAccessor} due to following reasons: *

    *
  • * Preventing hard-dependency to {@link sun.misc.Unsafe}/ *
  • *
  • * Some platforms (such as SPARC) don't support unaligned memory access. * So on these platforms memory access alignments must be checked and handled if possible. *
  • *
*

*/ @Deprecated @PrivateApi public final class UnsafeHelper { /** * @deprecated {@link GlobalMemoryAccessorRegistry#MEM} instead */ @Deprecated public static final Unsafe UNSAFE; /** * @deprecated {@link GlobalMemoryAccessorRegistry#MEM_AVAILABLE} instead */ @Deprecated public static final boolean UNSAFE_AVAILABLE; public static final long BYTE_ARRAY_BASE_OFFSET; public static final long BOOLEAN_ARRAY_BASE_OFFSET; public static final long SHORT_ARRAY_BASE_OFFSET; public static final long CHAR_ARRAY_BASE_OFFSET; public static final long INT_ARRAY_BASE_OFFSET; public static final long FLOAT_ARRAY_BASE_OFFSET; public static final long LONG_ARRAY_BASE_OFFSET; public static final long DOUBLE_ARRAY_BASE_OFFSET; public static final int BOOLEAN_ARRAY_INDEX_SCALE; public static final int BYTE_ARRAY_INDEX_SCALE; public static final int SHORT_ARRAY_INDEX_SCALE; public static final int CHAR_ARRAY_INDEX_SCALE; public static final int INT_ARRAY_INDEX_SCALE; public static final int FLOAT_ARRAY_INDEX_SCALE; public static final int LONG_ARRAY_INDEX_SCALE; public static final int DOUBLE_ARRAY_INDEX_SCALE; public static final int MEM_COPY_THRESHOLD = 1024 * 1024; private static final String UNSAFE_MODE_PROPERTY_NAME = "hazelcast.unsafe.mode"; private static final String UNSAFE_EXPLICITLY_DISABLED = "disabled"; private static final String UNSAFE_EXPLICITLY_ENABLED = "enforced"; private static final String UNSAFE_WARNING_WHEN_NOT_FOUND = "sun.misc.Unsafe isn't available, some features might " + "be not available"; private static final String UNSAFE_WARNING_WHEN_EXPLICTLY_DISABLED = "sun.misc.Unsafe has been disabled " + "via System Property " + UNSAFE_MODE_PROPERTY_NAME + ", some features might be not available."; private static final String UNSAFE_WARNING_WHEN_UNALIGNED_ACCESS_NOT_ALLOWED = "sun.misc.Unsafe has been disabled " + "because your platform does not support unaligned access to memory, some features might be not available."; private static final String UNSAFE_WARNING_WHEN_ENFORCED_ON_PLATFORM_WHERE_NOT_SUPPORTED = "You platform does not " + "seem to support unaligned access to memory. Unsafe usage has been enforced via System Property " + UNSAFE_MODE_PROPERTY_NAME + " This is not a supported configuration and it can crash JVM or corrupt your data!"; static { Unsafe unsafe; try { unsafe = findUnsafeIfAllowed(); } catch (RuntimeException e) { unsafe = null; } UNSAFE = unsafe; BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class, unsafe); BOOLEAN_ARRAY_BASE_OFFSET = arrayBaseOffset(boolean[].class, unsafe); SHORT_ARRAY_BASE_OFFSET = arrayBaseOffset(short[].class, unsafe); CHAR_ARRAY_BASE_OFFSET = arrayBaseOffset(char[].class, unsafe); INT_ARRAY_BASE_OFFSET = arrayBaseOffset(int[].class, unsafe); FLOAT_ARRAY_BASE_OFFSET = arrayBaseOffset(float[].class, unsafe); LONG_ARRAY_BASE_OFFSET = arrayBaseOffset(long[].class, unsafe); DOUBLE_ARRAY_BASE_OFFSET = arrayBaseOffset(double[].class, unsafe); BYTE_ARRAY_INDEX_SCALE = arrayIndexScale(byte[].class, unsafe); BOOLEAN_ARRAY_INDEX_SCALE = arrayIndexScale(boolean[].class, unsafe); SHORT_ARRAY_INDEX_SCALE = arrayIndexScale(short[].class, unsafe); CHAR_ARRAY_INDEX_SCALE = arrayIndexScale(char[].class, unsafe); INT_ARRAY_INDEX_SCALE = arrayIndexScale(int[].class, unsafe); FLOAT_ARRAY_INDEX_SCALE = arrayIndexScale(float[].class, unsafe); LONG_ARRAY_INDEX_SCALE = arrayIndexScale(long[].class, unsafe); DOUBLE_ARRAY_INDEX_SCALE = arrayIndexScale(double[].class, unsafe); boolean unsafeAvailable = false; try { // test if unsafe has required methods... if (unsafe != null) { long arrayBaseOffset = unsafe.arrayBaseOffset(byte[].class); byte[] buffer = new byte[(int) arrayBaseOffset + (2 * Bits.LONG_SIZE_IN_BYTES)]; unsafe.putByte(buffer, arrayBaseOffset, (byte) 0x00); unsafe.putBoolean(buffer, arrayBaseOffset, false); unsafe.putChar(buffer, normalize(arrayBaseOffset, Bits.CHAR_SIZE_IN_BYTES), '0'); unsafe.putShort(buffer, normalize(arrayBaseOffset, Bits.SHORT_SIZE_IN_BYTES), (short) 1); unsafe.putInt(buffer, normalize(arrayBaseOffset, Bits.INT_SIZE_IN_BYTES), 2); unsafe.putFloat(buffer, normalize(arrayBaseOffset, Bits.FLOAT_SIZE_IN_BYTES), 3f); unsafe.putLong(buffer, normalize(arrayBaseOffset, Bits.LONG_SIZE_IN_BYTES), 4L); unsafe.putDouble(buffer, normalize(arrayBaseOffset, Bits.DOUBLE_SIZE_IN_BYTES), 5d); unsafe.copyMemory(new byte[buffer.length], arrayBaseOffset, buffer, arrayBaseOffset, buffer.length); unsafeAvailable = true; } } catch (Throwable e) { Logger.getLogger(UnsafeHelper.class).warning(UNSAFE_WARNING_WHEN_NOT_FOUND); } UNSAFE_AVAILABLE = unsafeAvailable; } private UnsafeHelper() { } private static long arrayBaseOffset(Class type, Unsafe unsafe) { return unsafe == null ? -1 : unsafe.arrayBaseOffset(type); } private static int arrayIndexScale(Class type, Unsafe unsafe) { return unsafe == null ? -1 : unsafe.arrayIndexScale(type); } static Unsafe findUnsafeIfAllowed() { if (isUnsafeExplicitlyDisabled()) { Logger.getLogger(UnsafeHelper.class).warning(UNSAFE_WARNING_WHEN_EXPLICTLY_DISABLED); return null; } if (!isUnalignedAccessAllowed()) { if (isUnsafeExplicitlyEnforced()) { Logger.getLogger(UnsafeHelper.class).warning(UNSAFE_WARNING_WHEN_ENFORCED_ON_PLATFORM_WHERE_NOT_SUPPORTED); } else { Logger.getLogger(UnsafeHelper.class).warning(UNSAFE_WARNING_WHEN_UNALIGNED_ACCESS_NOT_ALLOWED); return null; } } Unsafe unsafe = findUnsafe(); if (unsafe == null) { Logger.getLogger(UnsafeHelper.class).warning(UNSAFE_WARNING_WHEN_NOT_FOUND); } return unsafe; } private static boolean isUnsafeExplicitlyDisabled() { String mode = System.getProperty(UNSAFE_MODE_PROPERTY_NAME); return UNSAFE_EXPLICITLY_DISABLED.equals(mode); } private static boolean isUnsafeExplicitlyEnforced() { String mode = System.getProperty(UNSAFE_MODE_PROPERTY_NAME); return UNSAFE_EXPLICITLY_ENABLED.equals(mode); } static boolean isUnalignedAccessAllowed() { return AlignmentUtil.isUnalignedAccessAllowed(); } private static Unsafe findUnsafe() { try { return Unsafe.getUnsafe(); } catch (SecurityException se) { return AccessController.doPrivileged(new PrivilegedAction() { @Override public Unsafe run() { try { Class type = Unsafe.class; try { Field field = type.getDeclaredField("theUnsafe"); field.setAccessible(true); return type.cast(field.get(type)); } catch (Exception e) { for (Field field : type.getDeclaredFields()) { if (type.isAssignableFrom(field.getType())) { field.setAccessible(true); return type.cast(field.get(type)); } } } } catch (Exception e) { throw new RuntimeException("Unsafe unavailable", e); } throw new RuntimeException("Unsafe unavailable"); } }); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy