| /** |
| * 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.hadoop.hbase.util; |
| |
| import java.lang.management.ManagementFactory; |
| import java.lang.management.OperatingSystemMXBean; |
| import java.lang.management.RuntimeMXBean; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| |
| import java.lang.reflect.Method; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.classification.InterfaceAudience; |
| import org.apache.hadoop.classification.InterfaceStability; |
| |
| |
| /** |
| * This class is a wrapper for the implementation of |
| * com.sun.management.UnixOperatingSystemMXBean |
| * It will decide to use the sun api or its own implementation |
| * depending on the runtime (vendor) used. |
| */ |
| |
| @InterfaceAudience.Public |
| @InterfaceStability.Evolving |
| public class JVM { |
| private static final Log LOG = LogFactory.getLog(JVM.class); |
| private OperatingSystemMXBean osMbean; |
| |
| private static final boolean ibmvendor = |
| System.getProperty("java.vendor").contains("IBM"); |
| private static final boolean windows = |
| System.getProperty("os.name").startsWith("Windows"); |
| private static final boolean linux = |
| System.getProperty("os.name").startsWith("Linux"); |
| private static final String JVMVersion = System.getProperty("java.version"); |
| |
| /** |
| * Constructor. Get the running Operating System instance |
| */ |
| public JVM () { |
| this.osMbean = ManagementFactory.getOperatingSystemMXBean(); |
| } |
| |
| /** |
| * Check if the OS is unix. |
| * |
| * @return whether this is unix or not. |
| */ |
| public static boolean isUnix() { |
| if (windows) { |
| return false; |
| } |
| return (ibmvendor ? linux : true); |
| } |
| |
| /** |
| * Check if the finish() method of GZIPOutputStream is broken |
| * |
| * @return whether GZIPOutputStream.finish() is broken. |
| */ |
| public static boolean isGZIPOutputStreamFinishBroken() { |
| return ibmvendor && JVMVersion.contains("1.6.0"); |
| } |
| |
| /** |
| * Load the implementation of UnixOperatingSystemMXBean for Oracle jvm |
| * and runs the desired method. |
| * @param mBeanMethodName : method to run from the interface UnixOperatingSystemMXBean |
| * @return the method result |
| */ |
| private Long runUnixMXBeanMethod (String mBeanMethodName) { |
| Object unixos; |
| Class<?> classRef; |
| Method mBeanMethod; |
| |
| try { |
| classRef = Class.forName("com.sun.management.UnixOperatingSystemMXBean"); |
| if (classRef.isInstance(osMbean)) { |
| mBeanMethod = classRef.getMethod(mBeanMethodName, new Class[0]); |
| unixos = classRef.cast(osMbean); |
| return (Long)mBeanMethod.invoke(unixos); |
| } |
| } |
| catch(Exception e) { |
| LOG.warn("Not able to load class or method for" + |
| " com.sun.management.UnixOperatingSystemMXBean.", e); |
| } |
| return null; |
| } |
| |
| /** |
| * Get the number of opened filed descriptor for the runtime jvm. |
| * If Oracle java, it will use the com.sun.management interfaces. |
| * Otherwise, this methods implements it (linux only). |
| * @return number of open file descriptors for the jvm |
| */ |
| public long getOpenFileDescriptorCount() { |
| |
| Long ofdc; |
| |
| if (!ibmvendor) { |
| ofdc = runUnixMXBeanMethod("getOpenFileDescriptorCount"); |
| return (ofdc != null ? ofdc.longValue () : -1); |
| } |
| InputStream in = null; |
| BufferedReader output = null; |
| try { |
| //need to get the PID number of the process first |
| RuntimeMXBean rtmbean = ManagementFactory.getRuntimeMXBean(); |
| String rtname = rtmbean.getName(); |
| String[] pidhost = rtname.split("@"); |
| |
| //using linux bash commands to retrieve info |
| Process p = Runtime.getRuntime().exec( |
| new String[] { "bash", "-c", |
| "ls /proc/" + pidhost[0] + "/fdinfo | wc -l" }); |
| in = p.getInputStream(); |
| output = new BufferedReader(new InputStreamReader(in)); |
| String openFileDesCount; |
| if ((openFileDesCount = output.readLine()) != null) |
| return Long.parseLong(openFileDesCount); |
| } catch (IOException ie) { |
| LOG.warn("Not able to get the number of open file descriptors", ie); |
| } finally { |
| if (output != null) { |
| try { |
| output.close(); |
| } catch (IOException e) { |
| LOG.warn("Not able to close the InputStream", e); |
| } |
| } |
| if (in != null){ |
| try { |
| in.close(); |
| } catch (IOException e) { |
| LOG.warn("Not able to close the InputStream", e); |
| } |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * @see java.lang.management.OperatingSystemMXBean#getSystemLoadAverage |
| */ |
| public double getSystemLoadAverage() { |
| return osMbean.getSystemLoadAverage(); |
| } |
| |
| /** |
| * @return the physical free memory (not the JVM one, as it's not very useful as it depends on |
| * the GC), but the one from the OS as it allows a little bit more to guess if the machine is |
| * overloaded or not). |
| */ |
| public long getFreeMemory() { |
| if (ibmvendor){ |
| return 0; |
| } |
| |
| Long r = runUnixMXBeanMethod("getFreePhysicalMemorySize"); |
| return (r != null ? r : -1); |
| } |
| |
| |
| /** |
| * Workaround to get the current number of process running. Approach is the one described here: |
| * http://stackoverflow.com/questions/54686/how-to-get-a-list-of-current-open-windows-process-with-java |
| */ |
| public int getNumberOfRunningProcess(){ |
| if (!isUnix()){ |
| return 0; |
| } |
| |
| BufferedReader input = null; |
| try { |
| int count = 0; |
| Process p = Runtime.getRuntime().exec("ps -e"); |
| input = new BufferedReader(new InputStreamReader(p.getInputStream())); |
| while (input.readLine() != null) { |
| count++; |
| } |
| return count - 1; // -1 because there is a headline |
| } catch (IOException e) { |
| return -1; |
| } finally { |
| if (input != null){ |
| try { |
| input.close(); |
| } catch (IOException ignored) { |
| } |
| } |
| } |
| } |
| |
| /** |
| * Get the number of the maximum file descriptors the system can use. |
| * If Oracle java, it will use the com.sun.management interfaces. |
| * Otherwise, this methods implements it (linux only). |
| * @return max number of file descriptors the operating system can use. |
| */ |
| public long getMaxFileDescriptorCount() { |
| Long mfdc; |
| if (!ibmvendor) { |
| mfdc = runUnixMXBeanMethod("getMaxFileDescriptorCount"); |
| return (mfdc != null ? mfdc.longValue () : -1); |
| } |
| InputStream in = null; |
| BufferedReader output = null; |
| try { |
| //using linux bash commands to retrieve info |
| Process p = Runtime.getRuntime().exec(new String[] { "bash", "-c", "ulimit -n" }); |
| in = p.getInputStream(); |
| output = new BufferedReader(new InputStreamReader(in)); |
| String maxFileDesCount; |
| if ((maxFileDesCount = output.readLine()) != null) return Long.parseLong(maxFileDesCount); |
| } catch (IOException ie) { |
| LOG.warn("Not able to get the max number of file descriptors", ie); |
| } finally { |
| if (output != null) { |
| try { |
| output.close(); |
| } catch (IOException e) { |
| LOG.warn("Not able to close the reader", e); |
| } |
| } |
| if (in != null){ |
| try { |
| in.close(); |
| } catch (IOException e) { |
| LOG.warn("Not able to close the InputStream", e); |
| } |
| } |
| } |
| return -1; |
| } |
| } |