View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.pool.sizeof;
18  
19  import java.lang.management.GarbageCollectorMXBean;
20  import java.lang.management.ManagementFactory;
21  
22  import javax.management.MBeanServer;
23  import javax.management.ObjectName;
24  import javax.management.openmbean.CompositeData;
25  
26  /***
27   * Some useful information about this Runtime for us to do meaningful sizeOf measurements
28   *
29   * @author Chris Dennis
30   */
31  public final class JvmInformation {
32  
33      /***
34       * Size of a pointer in bytes on this runtime
35       */
36      public static final int POINTER_SIZE;
37      /***
38       * Size of a java pointer in bytes on this runtime (that differs when compressedOops are being used)
39       */
40      public static final int JAVA_POINTER_SIZE;
41      /***
42       * Minimal size an object will occupy on the heap
43       */
44      public static final int MINIMUM_OBJECT_SIZE;
45      /***
46       * Value when no padding is being done by the GC
47       *
48       * @see #MINIMUM_OBJECT_SIZE
49       */
50      public static final int OBJECT_ALIGNMENT = 8;
51  
52      static {
53          if (is64Bit()) {
54              if (isHotspotCompressedOops()) {
55                  POINTER_SIZE = 8;
56                  JAVA_POINTER_SIZE = 4;
57              } else {
58                  POINTER_SIZE = 8;
59                  JAVA_POINTER_SIZE = 8;
60              }
61          } else {
62              POINTER_SIZE = 4;
63              JAVA_POINTER_SIZE = 4;
64          }
65  
66          if (isHotspotConcurrentMarkSweepGC()) {
67              /*
68              * Hotpot's CMS garbage collector pads objects to ensure they are big enough
69              * for it's free-chunk metadata to be stored inside the space left unoccupied
70              * by the free of a minimally sized object.  Helpfully enough it doesn't tell
71              * tell the java.lang.instrumentation code about this.
72              */
73              if (is64Bit()) {
74                  MINIMUM_OBJECT_SIZE = 24;
75              } else {
76                  MINIMUM_OBJECT_SIZE = 16;
77              }
78          } else {
79              MINIMUM_OBJECT_SIZE = OBJECT_ALIGNMENT;
80          }
81      }
82  
83      private JvmInformation() {
84  
85      }
86  
87      private static boolean is64Bit() {
88          String systemProp;
89          systemProp = System.getProperty("com.ibm.vm.bitmode");
90          if (systemProp != null) {
91              return systemProp.equals("64");
92          }
93          systemProp = System.getProperty("sun.arch.data.model");
94          if (systemProp != null) {
95              return systemProp.equals("64");
96          }
97          systemProp = System.getProperty("java.vm.version");
98          if (systemProp != null) {
99              return systemProp.contains("_64");
100         }
101         return false;
102     }
103 
104     private static boolean isHotspotCompressedOops() {
105         String value = getVmOptionValue("UseCompressedOops");
106         if (value == null) {
107             return false;
108         } else {
109             return Boolean.valueOf(value);
110         }
111     }
112 
113     private static boolean isHotspotConcurrentMarkSweepGC() {
114         for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
115             if ("ConcurrentMarkSweep".equals(bean.getName())) {
116                 return true;
117             }
118         }
119         return false;
120     }
121 
122     private static String getVmOptionValue(String name) {
123         try {
124             MBeanServer server = ManagementFactory.getPlatformMBeanServer();
125             ObjectName beanName = ObjectName.getInstance("com.sun.management:type=HotSpotDiagnostic");
126             Object vmOption = server.invoke(beanName, "getVMOption", new Object[] {name}, new String[] {"java.lang.String"});
127             return (String)((CompositeData)vmOption).get("value");
128         } catch (Throwable t) {
129             return null;
130         }
131     }
132 }