001 package com.softnetConsult.utils.sys; 002 003 import java.io.File; 004 import java.io.FileInputStream; 005 import java.io.IOException; 006 007 import com.softnetConsult.utils.reflect.ClassTools; 008 import com.softnetConsult.utils.reflect.ClassVersionInfo; 009 010 /** 011 * Static system, memory and time management utility functions. 012 * 013 * <p style="font-size:smaller;">This product includes software developed by the 014 * <strong>SoftNet-Consult Java Utility Library</strong> project and its contributors.<br /> 015 * (<a href="http://java-tools.sourceforge.net" target="_blank">http://java-tools.sourceforge.net</a>)<br /> 016 * Copyright (c) 2007-2008 SoftNet-Consult.<br /> 017 * Copyright (c) 2007-2008 G. Paperin.<br /> 018 * All rights reserved. 019 * </p> 020 * <p style="font-size:smaller;">File: SystemTools.java<br /> 021 * Library API version: {@value com.softnetConsult.utils.APIProperties#apiVersion}<br /> 022 * Java compliance version: {@value com.softnetConsult.utils.APIProperties#javaComplianceVersion} 023 * </p> 024 * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or 025 * without modification, are permitted provided that the following terms and conditions are met: 026 * </p> 027 * <p style="font-size:smaller;">1. Redistributions of source code must retain the above 028 * acknowledgement of the SoftNet-Consult Java Utility Library project, the above copyright 029 * notice, this list of conditions and the following disclaimer.<br /> 030 * 2. Redistributions in binary form must reproduce the above acknowledgement of the 031 * SoftNet-Consult Java Utility Library project, the above copyright notice, this list of 032 * conditions and the following disclaimer in the documentation and/or other materials 033 * provided with the distribution.<br /> 034 * 3. All advertising materials mentioning features or use of this software or any derived 035 * software must display the following acknowledgement:<br /> 036 * <em>This product includes software developed by the SoftNet-Consult Java Utility Library 037 * project and its contributors.</em> 038 * </p> 039 * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 040 * OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 041 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 042 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 043 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 044 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 045 * </p> 046 * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>) 047 * @version {@value com.softnetConsult.utils.APIProperties#apiVersion} 048 * 049 */ 050 public final class SystemTools { 051 052 /** 053 * Prevents instances of this class from being created 054 * as this class contains only static utility methods. 055 */ 056 private SystemTools() {} 057 058 059 /** 060 * Fetches the current memory information and formats the data in a human readable string. 061 * 062 * @return A human readable string containing information on available free memory, memory 063 * used by the current application, the total memory size of the current JVM and the maximum 064 * amount of memory that the current JVM will attempt to use. 065 */ 066 public static String getMemInfoString() { 067 Runtime rt = Runtime.getRuntime(); 068 long free = rt.freeMemory(); 069 long total = rt.totalMemory(); 070 long max = rt.maxMemory(); 071 String s = String.format("Memory info: Free: %,d KB; Used: %,d; Total: %,d KB; Max: %,d KB.", 072 free >>> 10, (total - free) >>> 10, total >>> 10, max >>> 10); 073 return s; 074 } 075 076 077 /** 078 * Prints a human readable line with the current memory information to std-out, 079 * equivalent to {@code System.out.println(getMemInfoString())}. 080 * 081 */ 082 public static void printMemInfoLine() { 083 System.out.println(getMemInfoString()); 084 } 085 086 087 /** 088 * Allows calling {@code Thread.sleep} without the nuisance of surrounding the call with 089 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored. 090 * 091 * @param millis The length of time to sleep in milliseconds. 092 */ 093 public static void sleep(long millis) { 094 try { 095 Thread.sleep(millis); 096 } catch(InterruptedException e) { } 097 } 098 099 100 /** 101 * Allows calling {@code Thread.sleep} without the nuisance of surrounding the call with 102 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored. 103 * 104 * @param millis The length of time to sleep in milliseconds. 105 * @param nanos 0-999999 additional nanoseconds to sleep. 106 */ 107 public static void sleep(long millis, int nanos) { 108 try { 109 Thread.sleep(millis, nanos); 110 } catch(InterruptedException e) { } 111 } 112 113 114 /** 115 * Allows calling {@code Object.wait} without the nuisance of surrounding the call with 116 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored. 117 * 118 * @param millis The length of time to sleep in milliseconds. 119 * @param object The object for which to wait. 120 */ 121 public static void wait(long millis, Object object) { 122 try { 123 object.wait(millis); 124 } catch(InterruptedException e) { } 125 } 126 127 128 /** 129 * Allows calling {@code Object.wait} without the nuisance of surrounding the call with 130 * a {@code try-catch} block. A possible {@code InterruptedException} is caught and ignored. 131 * 132 * @param millis The length of time to sleep in milliseconds. 133 * @param nanos 0-999999 additional nanoseconds to sleep. 134 * @param object The object for which to wait. 135 */ 136 public static void wait(long millis, int nanos, Object object) { 137 try { 138 object.wait(millis, nanos); 139 } catch(InterruptedException e) { } 140 } 141 142 143 /** 144 * Determines how many days, hours, minutes, seconds and milliseconds the specified time 145 * period contains. 146 * Note that the specified time period, i.e. the absolude difference between {@code startMillis} 147 * and {@code endMillis} may not be larger than {@code 185542587187199999L} milliseconds, as an internal 148 * overflow would occur otherwise. The limit of {@code 185542587187199999L milliseconds} corrsponds to 149 * {@code ( (Integer.MAX_VALUE + 1L) * 86400000L - 1L ) milliseconds} or 150 * {@code Integer.MAX_VALUE days, 23 hours, 59 minures and 59.999 seconds} or 151 * {@code 2147483647 days, 23:59:59.999}. 152 * 153 * @param startMillis The milliseconds marking the beginning of a time period. 154 * @param endMillis The milliseconds marking the end of a time period. 155 * 156 * @return An {@code int}-array containg exactly 5 following elements:<br /> 157 * index {@code [4]}: number of whole days in the specified time period;<br /> 158 * index {@code [3]}: number of whole hours not covered by the whole days in the specified time period;<br /> 159 * index {@code [2]}: number of whole minutes not covered by the whole hours in the specified time period;<br /> 160 * index {@code [1]}: number of whole seconds not covered by the whole mins in the specified time period;<br /> 161 * index {@code [0]}: number of whole millisecs not covered by the whole secs in the specified time period;<br /> 162 * 163 * @throws IllegalArgumentException If the absolute value of the difference between {@code startMillis} 164 * and {@code endMillis} is larger than {@code 185542587187199999L}. 165 */ 166 public static int[] timePeriod(long startMillis, long endMillis) { 167 168 long period = endMillis - startMillis; 169 if (0L > period) 170 period = -period; 171 172 if (period > 185542587187199999L) // 185542587187199999L = (Integer.MAX_VALUE + 1L) * 86400000L - 1L 173 throw new IllegalArgumentException("Cannot split a time period of longer " 174 + "than 185542587187199999L milliseconds"); 175 176 int[] dets = new int[5]; 177 dets[4] = (int) (period / 86400000L); // days 178 period = period % 86400000L; 179 dets[3] = (int) (period / 3600000L); // hours 180 period = period % 3600000L; 181 dets[2] = (int) (period / 60000L); // mins 182 period = period % 60000L; 183 dets[1] = (int) (period / 1000L); // secs 184 dets[0] = (int) (period % 1000L); // millis 185 return dets; 186 } 187 188 189 /** 190 * Formats a time interval to a nicely readable format without the need 191 * to involve a formatter. No validity checks are performed. 192 * 193 * @param millis Milliseconds 194 * @param secs Seconds. 195 * @param mins Minutes. 196 * @param hours Hours. 197 * @param days Days. 198 * @return Time formated as in for example {@code 3 days, 17:08:53.006}. 199 */ 200 public static String formatTime(int millis, int secs, int mins, int hours, int days) { 201 202 millis = (millis < 0 ? -millis : millis); 203 secs = (secs < 0 ? -secs : secs); 204 mins = (mins < 0 ? -mins : mins); 205 hours = (hours < 0 ? -hours : hours); 206 days = (days < 0 ? -days : days); 207 208 if (days > 1) { 209 return String.format("%d days, %02d:%02d:%02d.%03d", 210 days, hours, mins, secs, millis); 211 } else if (days == 1) { 212 return String.format("1 day, %02d:%02d:%02d.%03d", 213 hours, mins, secs, millis); 214 } else { 215 return String.format("%02d:%02d:%02d.%03d", 216 hours, mins, secs, millis); 217 } 218 } 219 220 221 /** 222 * Formats the specified time period as specified in {@link #formatTime(int, int, int, int, int)}; 223 * note that {@link #timePeriod(long, long)} is used to process the time period and therefore the 224 * same restrictions as in that method apply to this method. 225 * 226 * @param startMillis The milliseconds marking the beginning of a time period. 227 * @param endMillis The milliseconds marking the end of a time period. 228 * @return Time period formated as in for example {@code 3 days, 17:08:53.006}. 229 * @see #timePeriod(long, long) 230 * @see #formatTime(int, int, int, int, int) 231 */ 232 public static String formatTimePeriod(long startMillis, long endMillis) { 233 int[] timeDets = timePeriod(startMillis, endMillis); 234 return formatTime(timeDets[0], timeDets[1], timeDets[2], timeDets[3], timeDets[4]); 235 } 236 237 238 /** 239 * Gets the class version info of the specified Java class file. 240 * 241 * @param classfile A {@code File} representing a physical Java class file. 242 * @return A {@code ClassVersionInfo}-object containing information about the 243 * major and the minor versions of the specified class file as well as the minimum 244 * JVM version required to run that class file. If the specified file is not a valid 245 * Java class file (according to the magic numer check) this method returns {@code null}. 246 * @throws IOException If there was an error when reading the specified file. 247 */ 248 public static ClassVersionInfo getClassVersionInfo(File classfile) throws IOException { 249 FileInputStream in = new FileInputStream(classfile); 250 try { return ClassTools.getClassVersionInfo(in); } 251 finally { in.close(); } 252 } 253 254 /** 255 * Gets the class version info of the specified Java class file. 256 * 257 * @param classfile The full path of a physical Java class file. 258 * @return A {@code ClassVersionInfo}-object containing information about the 259 * major and the minor versions of the specified class file as well as the minimum 260 * JVM version required to run that class file. If the specified file is not a valid 261 * Java class file (according to the magic numer check) this method returns {@code null}. 262 * @throws IOException If there was an error when reading the specified file. 263 */ 264 public static ClassVersionInfo getClassVersionInfo(String classfile) throws IOException { 265 FileInputStream in = new FileInputStream(classfile); 266 try { return ClassTools.getClassVersionInfo(in); } 267 finally { in.close(); } 268 } 269 270 } // public class SystemTools