blob: 83e142218ec63b5635edbe21aa587bacb2b445b4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF 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 org.apache.geode.internal;
import org.apache.geode.InternalGemFireError;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.lang.SystemUtils;
import org.apache.geode.pdx.internal.unsafe.UnsafeWrapper;
import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
/**
* The class puts in one place the code that will determine the name of the GemFire shared library.
* This aids debugging.
*/
public class SharedLibrary {
/**
* A suffix added on to distinguish between the Linux and Solaris library names since they reside
* in the same directory.
*/
private final static String SOLARIS_LIBRARY_SUFFIX = "_sol";
private static final boolean is64Bit;
private static final int referenceSize;
private static final int objectHeaderSize;
private static final UnsafeWrapper unsafe;
static {
UnsafeWrapper tmp = null;
try {
tmp = new UnsafeWrapper();
} catch (RuntimeException ignore) {
} catch (Error ignore) {
}
unsafe = tmp;
}
static {
int sunbits = Integer.getInteger("sun.arch.data.model", 0).intValue(); // also used by JRockit
if (sunbits == 64) {
is64Bit = true;
} else if (sunbits == 32) {
is64Bit = false;
} else {
int ibmbits = Integer.getInteger("com.ibm.vm.bitmode", 0).intValue();
if (ibmbits == 64) {
is64Bit = true;
} else if (ibmbits == 32) {
is64Bit = false;
} else {
if (unsafe != null) {
is64Bit = unsafe.getAddressSize() == 8;
} else {
is64Bit = false;
}
}
}
if (!is64Bit) {
referenceSize = 4;
objectHeaderSize = 8;
} else {
int scaleIndex = 0;
int tmpReferenceSize = 0;
int tmpObjectHeaderSize = 0;
if (SystemUtils.isAzulJVM()) {
tmpObjectHeaderSize = 8;
tmpReferenceSize = 8;
} else {
if (unsafe != null) {
// Use unsafe to figure out the size of an object reference since we might
// be using compressed oops.
// Note: as of java 8 compressed oops do not imply a compressed object header.
// The object header is determined by UseCompressedClassPointers.
// UseCompressedClassPointers requires UseCompressedOops
// but UseCompressedOops does not require UseCompressedClassPointers.
// But it seems unlikely that someone would compress their oops
// not their class pointers.
scaleIndex = unsafe.arrayScaleIndex(Object[].class);
if (scaleIndex == 4) {
// compressed oops
tmpReferenceSize = 4;
tmpObjectHeaderSize = 12;
} else if (scaleIndex == 8) {
tmpReferenceSize = 8;
tmpObjectHeaderSize = 16;
} else {
System.out.println("Unexpected arrayScaleIndex " + scaleIndex
+ ". Using max heap size to estimate reference size.");
scaleIndex = 0;
}
}
if (scaleIndex == 0) {
// If our heap is > 32G (64G on java 8) then assume large oops. Otherwise assume
// compressed oops.
long SMALL_OOP_BOUNDARY = 32L;
if (SystemUtils.isJavaVersionAtLeast("1.8")) {
SMALL_OOP_BOUNDARY = 64L;
}
if (Runtime.getRuntime().maxMemory() > (SMALL_OOP_BOUNDARY * 1024 * 1024 * 1024)) {
tmpReferenceSize = 8;
tmpObjectHeaderSize = 16;
} else {
tmpReferenceSize = 4;
tmpObjectHeaderSize = 12;
}
}
}
referenceSize = tmpReferenceSize;
objectHeaderSize = tmpObjectHeaderSize;
}
}
/**
* @return true if this process is 64bit
* @throws RuntimeException if sun.arch.data.model doesn't fit expectations
*/
public static boolean is64Bit() {
return is64Bit;
}
/**
* @return true if this process is running on Solaris, no effort is made to distinguish between
* sparc and x86, the library will simply fail to load.
* @throws RuntimeException if sun.arch.data.model doesn't fit expectations
*/
public static boolean isSolaris() {
String osName = System.getProperty("os.name");
return osName.equals("SunOS");
}
/**
* Returns the os specific name of the GemFire shared library.
*/
public static String getName() {
StringBuffer result = new StringBuffer("gemfire");
if (isSolaris()) {
result.append(SOLARIS_LIBRARY_SUFFIX);
}
if (is64Bit()) {
result.append("64");
}
if (Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "debug")) {
result.append("_g");
}
return result.toString();
}
public static void loadLibrary(boolean debug) throws UnsatisfiedLinkError {
String library = getName();
try {
URL gemfireJarURL = GemFireVersion.getJarURL();
if (gemfireJarURL == null) {
throw new InternalGemFireError("Unable to locate jar file.");
}
String gemfireJar = null;
try {
gemfireJar = URLDecoder.decode(gemfireJarURL.getFile(), "UTF-8");
} catch (java.io.UnsupportedEncodingException uee) {
// This should never happen because UTF-8 is required to be implemented
throw new RuntimeException(uee);
}
int index = gemfireJar.lastIndexOf("/");
if (index == -1) {
throw new InternalGemFireError("Unable to parse gemfire jar path.");
}
String libDir = gemfireJar.substring(0, index + 1);
File libraryPath = new File(libDir, System.mapLibraryName(library));
if (libraryPath.exists()) {
System.load(libraryPath.getPath());
return;
}
} catch (InternalGemFireError ige) {
/**
* Unable to make a guess as to where the gemfire native library is based on its position
* relative to gemfire jar.
*/
if (debug) {
System.out.println("Problem loading library from URL path: " + ige);
}
} catch (UnsatisfiedLinkError ule) {
/**
* Unable to load the gemfire native library in the product tree, This is very unexpected and
* should not happen. Reattempting using System.loadLibrary
*/
if (debug) {
System.out.println("Problem loading library from URL path: " + ule);
}
}
System.loadLibrary(library);
}
/**
* Returns the size in bytes of a C pointer in this shared library, returns 4 for a 32 bit shared
* library, and 8 for a 64 bit shared library . This method makes a native call, so you can't use
* it to determine which library to load .
*
*/
public static int pointerSizeBytes() {
return SmHelper.pointerSizeBytes();
}
/**
* Accessor method for the is64Bit flag
*
* @return returns a boolean indicating if the 64bit native library was loaded.
* @since GemFire 5.1
*/
public static boolean getIs64Bit() {
return PureJavaMode.is64Bit();
}
public static int getReferenceSize() {
return referenceSize;
}
public static int getObjectHeaderSize() {
return objectHeaderSize;
}
}