View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.util;
20  
21  import java.lang.management.ManagementFactory;
22  import java.lang.management.OperatingSystemMXBean;
23  import java.lang.management.RuntimeMXBean;
24  
25  import java.io.BufferedReader;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import java.lang.reflect.Method;
33  
34  import org.apache.hadoop.classification.InterfaceAudience;
35  import org.apache.hadoop.classification.InterfaceStability;
36  
37  
38  /**
39   * This class is a wrapper for the implementation of
40   * com.sun.management.UnixOperatingSystemMXBean
41   * It will decide to use the sun api or its own implementation
42   * depending on the runtime (vendor) used.
43   */
44  
45  @InterfaceAudience.Public
46  @InterfaceStability.Evolving
47  public class JVM 
48  {
49    static final Logger LOG = LoggerFactory.getLogger(JVM.class);
50  
51    private OperatingSystemMXBean osMbean;
52  
53    private static final boolean ibmvendor =
54      System.getProperty("java.vendor").contains("IBM");
55    private static final boolean windows = 
56      System.getProperty("os.name").startsWith("Windows");
57    private static final boolean linux =
58      System.getProperty("os.name").startsWith("Linux");
59    private static final String JVMVersion = System.getProperty("java.version");
60  
61    /**
62     * Constructor. Get the running Operating System instance
63     */
64    public JVM () {
65      this.osMbean = ManagementFactory.getOperatingSystemMXBean();
66    }
67   
68    /**
69     * Check if the OS is unix. 
70     * 
71     * @return whether this is unix or not.
72     */
73    public static boolean isUnix() {
74      if (windows) {
75        return false;
76      }
77      return (ibmvendor ? linux : true);
78    }
79    
80    /**
81     * Check if the finish() method of GZIPOutputStream is broken
82     * 
83     * @return whether GZIPOutputStream.finish() is broken.
84     */
85    public static boolean isGZIPOutputStreamFinishBroken() {
86      return ibmvendor && JVMVersion.contains("1.6.0");
87    }
88  
89    /**
90     * Load the implementation of UnixOperatingSystemMXBean for Oracle jvm
91     * and runs the desired method. 
92     * @param mBeanMethodName : method to run from the interface UnixOperatingSystemMXBean
93     * @return the method result
94     */
95    private Long runUnixMXBeanMethod (String mBeanMethodName) {  
96      Object unixos;
97      Class<?> classRef;
98      Method mBeanMethod;
99  
100     try {
101       classRef = Class.forName("com.sun.management.UnixOperatingSystemMXBean");
102       if (classRef.isInstance(osMbean)) {
103         mBeanMethod = classRef.getDeclaredMethod(mBeanMethodName,
104           new Class[0]);
105         unixos = classRef.cast(osMbean);
106         return (Long)mBeanMethod.invoke(unixos);
107       }
108     }
109     catch(Exception e) {
110       LOG.warn("Not able to load class or method for com.sun.managment.UnixOperatingSystemMXBean.", e);
111     }
112     return null;
113   }
114 
115   /**
116    * Get the number of opened filed descriptor for the runtime jvm.
117    * If Oracle java, it will use the com.sun.management interfaces.
118    * Otherwise, this methods implements it (linux only).  
119    * @return number of open file descriptors for the jvm
120    */
121   public long getOpenFileDescriptorCount() {
122 
123     Long ofdc;
124     
125     if (!ibmvendor) {
126       ofdc = runUnixMXBeanMethod("getOpenFileDescriptorCount");
127       return (ofdc != null ? ofdc.longValue () : -1);
128     }
129     InputStream in = null;
130     BufferedReader output = null;
131     try {
132       //need to get the PID number of the process first
133       RuntimeMXBean rtmbean = ManagementFactory.getRuntimeMXBean();
134       String rtname = rtmbean.getName();
135       String[] pidhost = rtname.split("@");
136 
137       //using linux bash commands to retrieve info
138       Process p = Runtime.getRuntime().exec(
139       new String[] { "bash", "-c",
140           "ls /proc/" + pidhost[0] + "/fdinfo | wc -l" });
141       in = p.getInputStream();
142       output = new BufferedReader(new InputStreamReader(in));
143       String openFileDesCount;
144       if ((openFileDesCount = output.readLine()) != null)      
145              return Long.parseLong(openFileDesCount);
146      } catch (IOException ie) {
147        LOG.warn("Not able to get the number of open file descriptors", ie);
148      } finally {
149        if (output != null) {
150          try {
151            output.close();
152          } catch (IOException e) {
153            LOG.warn("Not able to close the InputStream", e);
154          }
155        }
156        if (in != null){
157          try {
158            in.close();
159          } catch (IOException e) {
160            LOG.warn("Not able to close the InputStream", e);
161          }
162        }
163     }
164     return -1;
165   }
166 
167   /**
168    * Get the number of the maximum file descriptors the system can use.
169    * If Oracle java, it will use the com.sun.management interfaces.
170    * Otherwise, this methods implements it (linux only).  
171    * @return max number of file descriptors the operating system can use.
172    */
173   public long getMaxFileDescriptorCount() {
174     Long mfdc;
175     if (!ibmvendor) {
176       mfdc = runUnixMXBeanMethod("getMaxFileDescriptorCount");
177       return (mfdc != null ? mfdc.longValue () : -1);
178     }
179     InputStream in = null;
180     BufferedReader output = null;
181     try {
182       //using linux bash commands to retrieve info
183       Process p = Runtime.getRuntime().exec(new String[] { "bash", "-c", "ulimit -n" });
184       in = p.getInputStream();
185       output = new BufferedReader(new InputStreamReader(in));
186       String maxFileDesCount;
187       if ((maxFileDesCount = output.readLine()) != null) return Long.parseLong(maxFileDesCount);
188     } catch (IOException ie) {
189       LOG.warn("Not able to get the max number of file descriptors", ie);
190     } finally {
191       if (output != null) {
192         try {
193           output.close();
194         } catch (IOException e) {
195           LOG.warn("Not able to close the reader", e);
196         }
197       }
198       if (in != null){
199         try {
200           in.close();
201         } catch (IOException e) {
202           LOG.warn("Not able to close the InputStream", e);
203         }
204       }
205     }
206     return -1;
207  }
208 }