blob: 1d90d7a6584cb10678a4f9fc23385c38dc592f4d [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.commons.lang3.JavaVersion;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.internal.lang.SystemUtils;
import org.apache.geode.unsafe.internal.sun.misc.Unsafe;
/**
* The class provides info about some JVM characteristics
*/
public class JvmSizeUtils {
private static final boolean is64Bit;
private static final int referenceSize;
private static final int objectHeaderSize;
@Immutable
private static final Unsafe unsafe;
static {
Unsafe tmp = null;
try {
tmp = new Unsafe();
} 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 (org.apache.commons.lang3.SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_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;
}
public static int getReferenceSize() {
return referenceSize;
}
public static int getObjectHeaderSize() {
return objectHeaderSize;
}
}