org.spf4j.base.Runtime Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spf4j-core Show documentation
Show all versions of spf4j-core Show documentation
A continuously growing collection of utilities to measure performance, get better diagnostics,
improve performance, or do things more reliably, faster that other open source libraries...
/*
* Copyright (c) 2001-2017, Zoltan Farkas All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Additionally licensed with:
*
* Licensed 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.spf4j.base;
import org.spf4j.os.OperatingSystem;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import org.spf4j.base.avro.ApplicationInfo;
import org.spf4j.base.avro.Organization;
import org.spf4j.concurrent.UIDGenerator;
import org.spf4j.io.ByteArrayBuilder;
import org.spf4j.jmx.JmxExport;
import org.spf4j.jmx.Registry;
import org.spf4j.os.ProcessHandler;
import org.spf4j.os.ProcessResponse;
import org.spf4j.os.ProcessUtil;
import org.spf4j.recyclable.impl.ArraySuppliers;
import org.spf4j.unix.CLibrary;
import org.spf4j.unix.JVMArguments;
import org.spf4j.unix.Lsof;
import org.spf4j.unix.UnixRuntime;
/**
*
* @author zoly
*/
@SuppressFBWarnings("PATH_TRAVERSAL_IN")
public final class Runtime {
public static final boolean IS_LITTLE_ENDIAN = "little".equals(System.getProperty("sun.cpu.endian"));
public static final String TMP_FOLDER = System.getProperty("java.io.tmpdir");
public static final Path TMP_FOLDER_PATH = Paths.get(TMP_FOLDER);
public static final String JAVA_VERSION = System.getProperty("java.version");
public static final String USER_NAME = System.getProperty("user.name");
public static final String USER_DIR = System.getProperty("user.dir");
public static final String USER_HOME = System.getProperty("user.home");
public static final String JAVA_HOME = System.getProperty("java.home");
/**
* Unix PID identifying your process in the OC image it is running.
*/
public static final int PID = ProcessUtil.getPid();
public static final String PROCESS_NAME;
public static final String OS_NAME = OperatingSystem.getOsName();
/**
* a unique ID for this JVM process.
* PID@HOSTNAME:HEXNR
*/
public static final String PROCESS_ID;
public static final int NR_PROCESSORS;
public static final Version JAVA_PLATFORM;
private static final java.lang.Runtime JAVA_RUNTIME = java.lang.Runtime.getRuntime();
static {
// priming certain functionality to make sure it works when we need it (classes are already loaded).
try (PrintStream stream = new PrintStream(new ByteArrayBuilder(), false, "UTF-8")) {
RuntimeException rex = new RuntimeException("priming");
Throwables.writeTo(rex, stream, Throwables.PackageDetail.NONE);
Throwables.containsNonRecoverable(rex);
} catch (UnsupportedEncodingException ex) {
throw new ExceptionInInitializerError(ex);
}
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
final int availableProcessors = JAVA_RUNTIME.availableProcessors();
if (availableProcessors <= 0) {
ErrLog.error("Invalid number of processors " + availableProcessors
+ " defaulting to 1");
NR_PROCESSORS = 1;
} else {
NR_PROCESSORS = availableProcessors;
}
String mxBeanName = runtimeMxBean.getName();
PROCESS_NAME = System.getProperty("spf4j.processName", mxBeanName);
boolean useUIDGeneratorForJvmId = Boolean.getBoolean("spf4j.useUIDForProcessId");
PROCESS_ID = useUIDGeneratorForJvmId ? UIDGenerator.generateIdBase("J", '-').toString()
: mxBeanName + ':' + Long.toHexString((System.currentTimeMillis() - 1509741164184L) / 1000);
JAVA_PLATFORM = Version.fromSpecVersion(JAVA_VERSION);
if (Boolean.getBoolean("spf4j.runtime.jmx")) {
Registry.export(Jmx.class);
}
}
public enum Version {
V1_0, V1_1, V1_2, V1_3, V1_4, V1_5, V1_6, V1_7, V1_8, V1_9, V_10, V_11, V_12, V_13, V_14, V_15, V_16, V_17;
@SuppressFBWarnings("PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS") // not really redundant
public static Version fromSpecVersion(final String specVersion) {
String[] cmpnts = specVersion.split("\\.");
if (cmpnts.length > 1) {
return Version.values()[Integer.parseInt(cmpnts[1])];
} else if (cmpnts.length == 1) {
return Version.values()[Integer.parseInt(cmpnts[0])];
} else {
throw new IllegalArgumentException("Unsupported specVersion: " + specVersion);
}
}
}
private Runtime() {
}
public static org.spf4j.base.Version getAppVersion() {
return new org.spf4j.base.Version(getAppVersionString());
}
public static String getAppVersionString() {
Class> mainClass = getMainClass();
String version = mainClass.getPackage().getImplementationVersion();
if (version == null) {
return "N/A";
} else {
return version;
}
}
/**
* Returns application information.
* Information is retrieved from the app jar manifest.
* Manifest can be generated with maven like:
*
*
* {@code
*
* org.apache.maven.plugins
* maven-jar-plugin
* 3.1.1
*
*
* true
*
* true
* true
* lib/
* org.spf4j.demo.Main
*
*
* ${project.groupId}
* ${project.groupId}
* ${project.artifactId}
* ${project.version}
* ${project.description}
* ${project.url}
* ${project.organization.name}
* ${project.organization.url}
* ${buildNumber}
* ${maven.build.timestamp}
*
*
*
*
*
*
* }
*
* @return
*/
public static ApplicationInfo getApplicationInfo() {
Class> mainClass = getMainClass();
if (mainClass == null) {
try {
return new ApplicationInfo("N/A", "N/A main class", new URL("file://manifest/Implementation-Url"), null);
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
}
Package p = mainClass.getPackage();
if (p == null) {
try {
return new ApplicationInfo("N/A", "N/A package Info", new URL("file://manifest/Implementation-Url"), null);
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
}
URL jarSourceUrl = PackageInfo.getJarSourceUrl(mainClass);
String implementationTitle = p.getImplementationTitle();
if (implementationTitle == null) {
implementationTitle = "N/A manifest:Implementation-Title";
}
if (jarSourceUrl == null) {
try {
return new ApplicationInfo(implementationTitle, "N/A jar",
new URL("file://manifest/Implementation-Url"), null);
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
}
try {
Manifest manifest = Reflections.getManifest(jarSourceUrl);
if (manifest == null) {
try {
return new ApplicationInfo(implementationTitle, "N/A jar manifest",
new URL("file://manifest/Implementation-Url"), null);
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
}
Attributes mainAttributes = manifest.getMainAttributes();
String appDescription = mainAttributes.getValue("Implementation-Description");
String appUrl = mainAttributes.getValue("Implementation-Url");
String org = mainAttributes.getValue("Implementation-Org");
String orgUrl = mainAttributes.getValue("Implementation-Org-Url");
return new ApplicationInfo(implementationTitle, appDescription == null ? "" : appDescription,
(appUrl == null || appUrl.trim().isEmpty())
? new URL("file://manifest/Implementation-Url") : new URL(appUrl),
(org != null && !org.trim().isEmpty()) ? new Organization(org,
new URL((orgUrl == null || orgUrl.trim().isEmpty())
? "file://manifest/Implementation-Org-Url" : orgUrl)) : null);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public static boolean isShuttingDown() {
try {
java.lang.Runtime runtime = java.lang.Runtime.getRuntime();
Thread dummy = new Thread(AbstractRunnable.NOP);
runtime.addShutdownHook(dummy);
runtime.removeShutdownHook(dummy);
} catch (IllegalStateException e) {
return true;
}
return false;
}
/**
* @deprecated use equivalent from ErrLog
*/
@Deprecated
public static void error(final String message) {
ErrLog.error(message);
}
/**
* @deprecated use equivalent from ErrLog
*/
@Deprecated
public static void error(final String message, final Throwable t) {
ErrLog.error(message, t);
}
/**
* @deprecated use equivalent from ErrLog
*/
@Deprecated
public static void errorNoPackageDetail(final String message, final Throwable t) {
ErrLog.errorNoPackageDetail(message, t);
}
public static void goDownWithError(final SysExits exitCode) {
goDownWithError(null, exitCode.exitCode());
}
public static void goDownWithError(@Nullable final Throwable t, final SysExits exitCode) {
goDownWithError(t, exitCode.exitCode());
}
// Calling Halt is the only sensible thing to do when the JVM is hosed.
@SuppressFBWarnings("MDM_RUNTIME_EXIT_OR_HALT")
public static void goDownWithError(@Nullable final Throwable t, final int exitCode) {
try {
// we cannot rely on the logging system to emit logs before a halt. (due to async backends)
if (t != null) {
ErrLog.error("Error, going down with exit code " + exitCode, t);
} else {
ErrLog.error("Error, going down with exit code " + exitCode);
}
} finally {
JAVA_RUNTIME.halt(exitCode);
}
}
/**
* @return true on macosx.
* @deprecated use OperatingSystem
*/
@Deprecated
public static boolean isMacOsx() {
return OperatingSystem.isMacOsx();
}
/**
*
* @return true on windows.
* @deprecated use OperatingSystem
*/
@Deprecated
public static boolean isWindows() {
return OperatingSystem.isWindows();
}
public static boolean isTestFramework() {
StackTraceElement[][] stackTraces = Threads.getStackTraces(Threads.getThreads());
for (StackTraceElement[] sts : stackTraces) {
if (sts != null) {
for (StackTraceElement ste : sts) {
String className = ste.getClassName();
if (className.startsWith("org.junit") || className.startsWith("org.openjdk.jmh")) {
return true;
}
}
}
}
return false;
}
/**
* @return true if jna platform is present.
* @deprecated use JNA instead
*/
@Deprecated
public static boolean haveJnaPlatform() {
return JNA.haveJnaPlatform();
}
/**
* @return true if jna platform clib is present.
* @deprecated use JNA instead.
*/
@Deprecated
public static boolean haveJnaPlatformClib() {
return JNA.haveJnaPlatformClib();
}
/**
* get the number of open files by current java process.
*
* @return -1 if cannot get nr of open files
* @deprecated use OperatingSystem.getOpenFileDescriptorCount() instead
*/
@CheckReturnValue
@Deprecated
public static int getNrOpenFiles() {
return (int) OperatingSystem.getOpenFileDescriptorCount();
}
/**
* @deprecated use Lsof.getLsofOutput instead.
*/
@Nullable
@CheckReturnValue
@Deprecated
public static CharSequence getLsofOutput() {
return Lsof.getLsofOutput();
}
/**
* @deprecated use Processhandler
*/
@Deprecated
public interface ProcOutputHandler {
void handleStdOut(byte[] bytes, int length);
void stdOutDone();
void handleStdErr(byte[] bytes, int length);
void stdErrDone();
}
/**
* @deprecated use OperatingSystem.forkExec.
*/
@Deprecated
public static CharSequence run(final String[] command,
final long timeoutMillis) throws IOException, InterruptedException, ExecutionException, TimeoutException {
return OperatingSystem.forkExec(command, timeoutMillis);
}
/**
* @deprecated use OperatingSystem.killProcess.
*/
@Deprecated
public static int killProcess(final Process proc, final long terminateTimeoutMillis,
final long forceTerminateTimeoutMillis)
throws InterruptedException, TimeoutException {
return OperatingSystem.killProcess(proc, terminateTimeoutMillis, forceTerminateTimeoutMillis);
}
/**
* @deprecated use OperatingSystem.forkExec instead.
*/
public static int run(final String[] command, final ProcOutputHandler handler,
final long timeoutMillis)
throws IOException, InterruptedException, ExecutionException, TimeoutException {
return run(command, handler, timeoutMillis, 60000);
}
/**
* @deprecated use OperatingSystem.forkExec instead.
*/
@SuppressFBWarnings("COMMAND_INJECTION")
@Deprecated
public static int run(final String[] command, final ProcOutputHandler handler,
final long timeoutMillis, final long terminationTimeoutMillis)
throws IOException, InterruptedException, ExecutionException, TimeoutException {
ProcessResponse resp = OperatingSystem.forkExec(command,
new ProcessHandler() {
@Override
public Void handleStdOut(final InputStream is) throws IOException {
int cos;
byte[] buffer = ArraySuppliers.Bytes.TL_SUPPLIER.get(8192);
try {
while ((cos = is.read(buffer)) >= 0) {
handler.handleStdOut(buffer, cos);
}
} finally {
ArraySuppliers.Bytes.TL_SUPPLIER.recycle(buffer);
handler.stdOutDone();
}
return null;
}
@Override
public Void handleStdErr(final InputStream stderr) throws IOException {
int cos;
byte[] buffer = ArraySuppliers.Bytes.TL_SUPPLIER.get(8192);
try {
while ((cos = stderr.read(buffer)) >= 0) {
handler.handleStdErr(buffer, cos);
}
} finally {
ArraySuppliers.Bytes.TL_SUPPLIER.recycle(buffer);
handler.stdErrDone();
}
return null;
}
}, timeoutMillis, terminationTimeoutMillis);
return resp.getResponseCode();
}
/**
* @deprecated use ShutdownRunnable directly
*/
@Deprecated
public static void queueHookAtBeginning(final Runnable runnable) {
if (!ShutdownThread.get().queueHook(Integer.MIN_VALUE, runnable)) {
throw new RejectedExecutionException("Rejected " + runnable);
}
}
/**
* @deprecated use ShutdownRunnable directly
*/
@Deprecated
public static void queueHookAtEnd(final Runnable runnable) {
if (!ShutdownThread.get().queueHook(Integer.MAX_VALUE, runnable)) {
throw new RejectedExecutionException("Rejected " + runnable);
}
}
/**
* @deprecated use ShutdownRunnable directly
*/
@Deprecated
public static void queueHook(final int priority, final Runnable runnable) {
if (!ShutdownThread.get().queueHook(priority, runnable)) {
throw new RejectedExecutionException("Rejected " + runnable);
}
}
@Deprecated
public static boolean removeQueuedShutdownHook(final Runnable runnable) {
return ShutdownThread.get().removeQueuedShutdownHook(runnable);
}
/**
* @return returns the deadline as millis since epoch.
* @deprecated see ExecutionContexts.
*/
@Deprecated
public static long getDeadline() {
return Timing.getCurrentTiming().fromNanoTimeToEpochMillis(ExecutionContexts.getContextDeadlineNanos());
}
/**
* @return milliseconds until deadline.
* @deprecated see ExecutionContexts.
*/
@Deprecated
public static long millisToDeadline() throws TimeoutException {
return ExecutionContexts.getTimeToDeadline(TimeUnit.MILLISECONDS);
}
/**
* Attempts to run the GC in a verifiable way.
*
* @param timeoutMillis - timeout for GC attempt
* @return true if GC executed for sure, false otherwise, gc might have been executed though, but we cannot be sure.
*/
@SuppressFBWarnings
public static boolean gc(final long timeoutMillis) {
WeakReference
© 2015 - 2024 Weber Informatics LLC | Privacy Policy