All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.bedrock.jprofiler.JprofilerProfile Maven / Gradle / Ivy

There is a newer version: 5.1.7
Show newest version
/*
 * File: JprofilerProfile.java
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * The contents of this file are subject to the terms and conditions of 
 * the Common Development and Distribution License 1.0 (the "License").
 *
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the License by consulting the LICENSE.txt file
 * distributed with this file, or by consulting https://oss.oracle.com/licenses/CDDL
 *
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file LICENSE.txt.
 *
 * MODIFICATIONS:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 */

package com.oracle.bedrock.jprofiler;

import com.oracle.bedrock.Option;
import com.oracle.bedrock.OptionsByType;
import com.oracle.bedrock.runtime.Application;
import com.oracle.bedrock.runtime.MetaClass;
import com.oracle.bedrock.runtime.Platform;
import com.oracle.bedrock.runtime.Profile;
import com.oracle.bedrock.runtime.java.JavaApplication;
import com.oracle.bedrock.runtime.java.options.Freeform;
import com.oracle.bedrock.runtime.java.options.WaitToStart;
import com.oracle.bedrock.runtime.network.AvailablePortIterator;
import com.oracle.bedrock.util.Capture;
import com.oracle.bedrock.util.PerpetualIterator;

import java.io.File;
import java.net.InetAddress;

/**
 * The JProfiler {@link Profile}.
 * 

* Copyright (c) 2016. All Rights Reserved. Oracle Corporation.
* Oracle is a registered trademark of Oracle Corporation and/or its affiliates. * * @author Jonathan Knight */ public class JprofilerProfile implements Profile, Option { /** * JProfiler default listen port. */ private static final int DEFAULT_PORT = 8849; /** * The default listen address for JProfiler - equates to 0.0.0.0:8849 */ private static final ListenAddress DEFAULT_ADDRESS = new ListenAddress(DEFAULT_PORT); /** * Flag indicating whether this profile is enabled. */ private final boolean enabled; /** * The location of the JProfiler agent */ private final String agentLibraryFile; /** * The listen address to use. */ private final ListenAddress listenAddress; /** * Flag indicating whether the application will start suspended. */ private final boolean startSuspended; /** * Flaginidcating whether the application will run JProfiler in offline mode. */ private final boolean offline; /** * The JProfiler configuration file to use in offline mode. */ private final File configurationFile; /** * The JProfiler session ID to use in offline mode. */ private final int sessionId; /** * Flag indicating whether JProfiler prints the names of all instrumented classes to stderr */ private final boolean verbose; /** * Enables the detection of object allocations via JNI calls */ private final boolean jniInterception; /** * stack size for dynamic instrumentation. */ private final Integer stack; /** * stack size for sampling. */ private final Integer samplingStack; /** * Constructs a {@link JprofilerProfile}. * * @param enabled enabling * @param agentLibraryFile the agent library file * @param listenAddress the {@link ListenAddress} * @param offline start offline * @param configurationFile the configuration file * @param sessionId the session id * @param startSuspended start suspended * @param verbose verbose output * @param jniInterception use JNI interception * @param stack the stack * @param samplingStack the sampling stack size */ public JprofilerProfile(boolean enabled, String agentLibraryFile, ListenAddress listenAddress, boolean offline, File configurationFile, int sessionId, boolean startSuspended, boolean verbose, boolean jniInterception, Integer stack, Integer samplingStack) { this.enabled = enabled; this.agentLibraryFile = agentLibraryFile; this.listenAddress = listenAddress; this.offline = offline; this.configurationFile = configurationFile; this.sessionId = sessionId; this.startSuspended = startSuspended; this.verbose = verbose; this.jniInterception = jniInterception; this.stack = stack; this.samplingStack = samplingStack; } /** * Obtain whether JProfiler is enabled. * * @return true if JProfiler is enabled otherwise false */ public boolean isEnabled() { return enabled; } /** * Run JProfiler in offline mode using the specified session ID from the file. * The configuration file used will be the default JProfiler configuration file * located in the .jprofiler directory in the current users home directory. * * @param sessionId the session id to use from the specified configuration file * * @return this {@link JprofilerProfile} for fluent method chaining * * @throws IllegalStateException if start suspended has been set to true */ public JprofilerProfile offlineMode(int sessionId) { return offlineMode(null, sessionId); } /** * Run JProfiler in offline mode using the specified configuration XML file * and the specified session ID from the file. * * @param configurationFile the configuration file to use for JProfiler * @param sessionId the session id to use from the specified configuration file * * @return this {@link JprofilerProfile} for fluent method chaining * * @throws IllegalStateException if start suspended has been set to true */ public JprofilerProfile offlineMode(File configurationFile, int sessionId) { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, true, configurationFile, sessionId, false, this.verbose, this.jniInterception, this.stack, this.samplingStack); } /** * Start the application in listen mode listening on the default * address and port. * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile listenMode() { return listenMode(DEFAULT_ADDRESS); } /** * Start the application in listen mode listening on the specified * {@link ListenAddress}. * * @param listenAddress the {@link ListenAddress} * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile listenMode(ListenAddress listenAddress) { return new JprofilerProfile(this.enabled, this.agentLibraryFile, listenAddress, false, this.configurationFile, this.sessionId, this.startSuspended, this.verbose, this.jniInterception, this.stack, this.samplingStack); } /** * Do not wait for JProfiler to connect when the application JVM starts. * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile noWait() { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, false, this.verbose, this.jniInterception, this.stack, this.samplingStack); } /** * Start the application suspended and wait for JProfiler to connect. * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile startSuspended() { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, true, this.verbose, this.jniInterception, this.stack, this.samplingStack); } /** * JProfiler will print the names of all instrumented classes to stderr. * * @param verbose true if JProfiler should run in verbose mode * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile verbose(boolean verbose) { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, this.startSuspended, verbose, this.jniInterception, this.stack, this.samplingStack); } /** * Enable the detection of object allocations via JNI calls. * * @param jniInterception flag indicating whether to enable JNI interception * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile jniInterception(boolean jniInterception) { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, this.startSuspended, this.verbose, jniInterception, this.stack, this.samplingStack); } /** * Set the maximum stack size for dynamic instrumentation. * Only change this parameter when JProfiler emits corresponding warning messages. * The default value is 10000 * * @param stack the maximum stack size for dynamic instrumentation * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile stack(int stack) { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, this.startSuspended, this.verbose, this.jniInterception, stack, this.samplingStack); } /** * Use the default stack size for dynamic instrumentation. * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile defaultStack() { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, this.startSuspended, this.verbose, this.jniInterception, null, this.samplingStack); } /** * Set the maximum stack size for sampling. Only change this parameter * when JProfiler emits corresponding warning messages. * The default value is 200. * * @param samplingStack the samplign stack size * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile samplingStack(int samplingStack) { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, this.startSuspended, this.verbose, this.jniInterception, this.stack, samplingStack); } /** * Use the default stack size for sampling. * * @return this {@link JprofilerProfile} for fluent method chaining */ public JprofilerProfile defaultSamplingStack() { return new JprofilerProfile(this.enabled, this.agentLibraryFile, this.listenAddress, this.offline, this.configurationFile, this.sessionId, this.startSuspended, this.verbose, this.jniInterception, this.stack, null); } @Override public void onLaunching(Platform platform, MetaClass metaClass, OptionsByType optionsByType) { if (metaClass != null && JavaApplication.class.isAssignableFrom(metaClass.getImplementationClass(platform, optionsByType)) && isEnabled()) { StringBuilder agentLib = new StringBuilder("-agentpath:").append(agentLibraryFile).append('='); if (offline) { agentLib.append("offline,id=").append(sessionId).append(",nowait"); if (configurationFile != null) { agentLib.append(",config=").append(configurationFile); } } else { ListenAddress address = this.listenAddress == null ? optionsByType.get(ListenAddress.class) : this.listenAddress; if (address == null) { address = DEFAULT_ADDRESS; } InetAddress listenAddress = address.getInetAddress(); if (listenAddress != null) { agentLib.append(",address=" + listenAddress.getHostName()); } agentLib.append(",port=").append(address.getPort().get()).append(startSuspended ? "" : ",nowait"); // replace the TransportAddress with the one we've resolved / created optionsByType.add(address); } if (verbose) { agentLib.append(",verbose-instr"); } if (jniInterception) { agentLib.append(",jniInterception"); } if (stack != null) { agentLib.append(",stack=").append(stack); } if (samplingStack != null) { agentLib.append(",samplingstack=").append(samplingStack); } // add the agent as a Freeform JvmOption optionsByType.add(new Freeform(agentLib.toString())); // disable waiting for the application to start if we're in suspend mode if (startSuspended) { optionsByType.add(WaitToStart.disabled()); } } } @Override public void onLaunched(Platform platform, Application application, OptionsByType optionsByType) { } @Override public void onClosing(Platform platform, Application application, OptionsByType optionsByType) { } /** * Create a {@link JprofilerProfile} that is enabled and will use the * JProfiler agent at the specified location. * * @param agentLibraryFile the location of the JProfiler agent * * @return an enabled {@link JprofilerProfile} */ public static JprofilerProfile enabled(String agentLibraryFile) { return new JprofilerProfile(true, agentLibraryFile, null, false, null, 0, true, false, false, null, null); } /** * Create a {@link JprofilerProfile} that is enabled and will use the * JProfiler agent at the specified location. The {@link JprofilerProfile} * instance will also be configured with the "nowait" setting that means * the application will not wait for JProfiler to connect when the JVM starts. * This can be changed by calling {@link #startSuspended()}. * * @param agentLibraryFile the location of the JProfiler agent * * @return an enabled {@link JprofilerProfile} */ @OptionsByType.Default public static JprofilerProfile enabledNoWait(String agentLibraryFile) { return new JprofilerProfile(true, agentLibraryFile, null, false, null, 0, false, false, false, null, null); } /** * Create a {@link JprofilerProfile} that is disabled. * * @return a {@link JprofilerProfile} that is disabled. */ public static JprofilerProfile disabled() { return new JprofilerProfile(false, null, null, false, null, 0, false, false, false, null, null); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } JprofilerProfile profile = (JprofilerProfile) o; if (enabled != profile.enabled) { return false; } if (startSuspended != profile.startSuspended) { return false; } if (offline != profile.offline) { return false; } if (sessionId != profile.sessionId) { return false; } if (verbose != profile.verbose) { return false; } if (jniInterception != profile.jniInterception) { return false; } if (agentLibraryFile != null ? !agentLibraryFile.equals(profile.agentLibraryFile) : profile.agentLibraryFile != null) { return false; } if (listenAddress != null ? !listenAddress.equals(profile.listenAddress) : profile.listenAddress != null) { return false; } if (configurationFile != null ? !configurationFile.equals(profile.configurationFile) : profile.configurationFile != null) { return false; } if (stack != null ? !stack.equals(profile.stack) : profile.stack != null) { return false; } return samplingStack != null ? samplingStack.equals(profile.samplingStack) : profile.samplingStack == null; } @Override public String toString() { StringBuilder str = new StringBuilder("JprofilerProfile("); if (enabled) { str.append("agentLibraryFile=").append(agentLibraryFile).append(", listenAddress=").append(listenAddress) .append(", offline=").append(offline).append(", configurationFile=").append(configurationFile) .append(", sessionId=").append(sessionId).append(", startSuspended=").append(startSuspended) .append(", verbose=").append(verbose).append(", jniInterception=").append(jniInterception) .append(", stack=") .append(stack == null ? "default" : stack).append(", samplingStack=") .append(samplingStack == null ? "default" : samplingStack); } else { str.append("disabled"); } str.append(')'); return str.toString(); } @Override public int hashCode() { int result = (enabled ? 1 : 0); result = 31 * result + (agentLibraryFile != null ? agentLibraryFile.hashCode() : 0); result = 31 * result + (listenAddress != null ? listenAddress.hashCode() : 0); result = 31 * result + (startSuspended ? 1 : 0); result = 31 * result + (offline ? 1 : 0); result = 31 * result + (configurationFile != null ? configurationFile.hashCode() : 0); result = 31 * result + sessionId; result = 31 * result + (verbose ? 1 : 0); result = 31 * result + (jniInterception ? 1 : 0); result = 31 * result + (stack != null ? stack.hashCode() : 0); result = 31 * result + (samplingStack != null ? samplingStack.hashCode() : 0); return result; } /** * The listen address that the application will use to listen * for JProfiler connections. */ public static class ListenAddress implements Option { /** * The optional address for listening for the JProfiler * (when null this implies all local addresses) */ private InetAddress address; /** * The port for listening for JProfiler connections. */ private Capture port; /** * Constructs a local {@link ListenAddress}, choosing a port from the * {@link AvailablePortIterator}. * * @param ports the available ports */ public ListenAddress(AvailablePortIterator ports) { this(ports.getInetAddresses().iterator().next(), new Capture<>(ports)); } /** * Constructs a local {@link ListenAddress} for the specified port. * * @param port the port */ public ListenAddress(Capture port) { this(null, port); } /** * Constructs a local {@link ListenAddress} for the specified port. * * @param port the port */ public ListenAddress(int port) { this(null, new Capture<>(new PerpetualIterator<>(port))); } /** * Constructs a {@link ListenAddress} with the specified port. * * @param address the address * @param port the port */ public ListenAddress(InetAddress address, Capture port) { if (port == null) { new Capture<>(new PerpetualIterator<>(DEFAULT_PORT)); } else { this.address = address; this.port = port; } } /** * Constructs a {@link ListenAddress} with the specified port. * * @param address the address * @param port the port */ public ListenAddress(InetAddress address, int port) { this(address, new Capture<>(new PerpetualIterator<>(port))); } /** * Obtains the address for the {@link JprofilerProfile} * listen address (which may be null). * * @return the {@link InetAddress} */ public InetAddress getInetAddress() { return address; } /** * Obtains the port for the {@link JprofilerProfile} listen address. * * @return the port */ public Capture getPort() { return port; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ListenAddress)) { return false; } ListenAddress other = (ListenAddress) o; if (address != null ? !address.equals(other.address) : other.address != null) { return false; } return port.equals(other.port); } @Override public int hashCode() { int result = address != null ? address.hashCode() : 0; result = 31 * result + port.hashCode(); return result; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy