This page describes setting up Stackdriver Profiler for profiling Java code. For Java, the Profiler offers CPU, heap, and wall-time profiling; see Profiling Concepts for more information.
You must use version 7, 8, 9 or 11 of either the OpenJDK or the Oracle JDK.
Setting up Profiler typically involves installing the profiling agent and loading it when you start Java, providing configuration values for the agent as arguments. If you are using Java, you can use the profiling agent on Linux in the following environments:
- Compute Engine
- Google Kubernetes Engine
- App Engine flexible environment
- App Engine standard environment (requires App Engine SDK version 1.9.64 or later)
You can also profile Java code on non-Google Cloud Platform systems. See Profiling Outside Google Cloud Platform for more information.
Enabling the Profiler API
Before you use the profiling agent, ensure that the underlying
Profiler API is enabled. You can check the status of the API and enable
it if necessary by using either the Cloud SDK gcloud command-line tool or
the Cloud Console:
Cloud SDK
If you have not already installed the Cloud SDK on your workstation, see Google Cloud SDK.
Run the following command:
gcloud services enable cloudprofiler.googleapis.com
For more information, see
gcloud services.
Cloud Console
Go to the APIs & Services dashboard:
Select the project you will use to access the API.
Click the Add APIs and Services button.
Search for Profiler API.
In the search results, select Stackdriver Profiler API.
If API enabled is displayed, then the API is already enabled. If not, click the Enable button.
Installing the Profiler agent
Compute Engine
Create a directory, for example, /opt/cprof, in which to
install Profiler:
sudo mkdir -p /opt/cprof
Download the agent archive from the storage.googleapis.com
repository and extract it into the installation directory:
wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
| sudo tar xzv -C /opt/cprofGKE
For GKE, modify the service container Dockerfile to create a directory in which to install Profiler, download the agent archive, and extract it into the installation directory:
RUN mkdir -p /opt/cprof && \
wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz \
| tar xzv -C /opt/cprofApp Engine flexible environment
When you use the Google Java 8 and Java 9 base images,
the Profiler agent is pre-installed.
If you use a base image from a different source or if you use a different
supported version of Java, then you need to install the agent.
For example, the following Dockerfile for Java 11 applications
loads the openjdk:11-slim image
and installs the Profiler agent:
FROM openjdk:11-slim
COPY . .
RUN apt-get update && apt-get install -y curl wget
RUN mkdir -p /opt/cprof && \
wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz | tar xzv -C /opt/cprof
ENTRYPOINT ["java", "-agentpath:/opt/cprof/profiler_java_agent.so=[OPTION1],[OPTION2]"]
App Engine standard environment
When you use the Google Java 8 runtime base image,
the Profiler agent is pre-installed.
If you use a base image from a different source or if you use a different
supported version of Java, then you need to install the agent.
For example, the following Dockerfile for Java 11 applications
loads the openjdk:11-slim image
and installs the Profiler agent:
FROM openjdk:11-slim
COPY . .
RUN apt-get update && apt-get install -y curl wget
RUN mkdir -p /opt/cprof && \
wget -q -O- https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz | tar xzv -C /opt/cprof
ENTRYPOINT ["java", "-agentpath:/opt/cprof/profiler_java_agent.so=[OPTION1],[OPTION2]"]
Loading the Profiler agent
To profile your code, start Java as you normally would to run your program, but specify the agent-configuration options. You specify the path to the agent library, and you can pass options to the library.
For the App Engine standard environment, the agent is automatically loaded and configured. Skip ahead to Starting your program, for details on configuring, and starting, your program.
Agent configuration
To configure the profiling agent, include the -agentpath flag when starting
your application:
-agentpath:[INSTALL_DIR]/profiler_java_agent.so=[OPTION1],[OPTION2],[OPTION3]
In this expression, [INSTALL_DIR] is the path to the profiling agent, while
[OPTION1], [OPTION2], and [OPTION3] are agent configuration options. For
example, if you replace [OPTION1] with -cprof_service=myapp in the previous
expression, then you set the service name to myapp. There is no restriction
on the number of options or their ordering. Supported configuration options
are listed in the following table:
| Agent option | Description |
|---|---|
-cprof_service
|
If your application isn't running on App Engine, then you must
use this configuration option to set the service name.
For service name restrictions, see
Service name and version arguments.
|
-cprof_service_version
|
When you want the ability to analyze profiling data using the Profiler UI by the version of the service, use this option to set the version. For version restrictions, see Service name and version arguments. |
-cprof_project_id
|
When you are running outside of GCP, use this option to specify your GCP project ID. For more information, see Profiling code outside Google Cloud Platform]. |
-cprof_zone_name
|
When your application is running on GCP, the profiling agent determines the zone by communicating with the Compute Engine metadata service. If the profiling agent can't communicate with the metadata service, then you need to use this option. |
-cprof_gce_metadata_server_retry_count-cprof_gce_metadata_server_retry_sleep_sec
|
Together, these two options define the retry policy that the profiler
agent uses when it communicates with the
Compute Engine metadata service.
to gather your GCP project ID and zone information.
Default policy is to retry up to 3 times waiting 1 second between attempts. This policy is sufficient for most configurations. |
-cprof_cpu_use_per_thread_timers
|
For the most accurate CPU utilization profiles, set this option
to true. Use of this option results in increased per-thread overhead.
Default value is false. |
-cprof_force_debug_non_safepoints
|
By default, the profiling agent forces JVM to generate debugging
information for all just in time (JIT) generated code, in addition
to generating debug information for all safepoints. This results in the
most accurate function and line-level location information for CPU and
heap profiles at the expense of additional agent overhead. You can disable
the generation of debugging information for JIT code by setting this
option to false. Default value is true. |
-cprof_wall_num_threads_cutoff
|
By default, wall profiles aren't collected if the total number of threads
in the application exceeds 4096. The limit ensures that during profile
collection, the cost of traversing the stack of threads is minimal.
If your service normally has more than 4096 threads and if you want
to collect profiling data at the expense of additional overhead, use
this flag to increase limit. Default limit is 4096 threads. |
-cprof_enable_heap_sampling-cprof_heap_sampling_interval
|
To enable heap profiling for Java 11, set-cprof_enable_heap_sampling to true.
The overhead of heap profiling is dependent on the
heap sampling interval. A high sampling interval, for example, 1000 bytes,
incurs significantly more overhead than the default sampling interval of
512k bytes.
By default, heap profiling is disabled. When enabled, the default setting for the sampling interval is 512k. |
Service name and version arguments
When you load the Profiler agent, you specify a service-name argument and an optional service-version argument to configure it.
The service name lets Profiler collect profiling data for all replicas of that service. The profiler service ensures a collection rate of one profile per minute, on average, for each service name across each combination service versions and zones.
For example, if you have a service with two versions running across replicas in three zones, the profiler will create an average of 6 profiles per minute for that service.
If you use different service names for your replicas, then your service will be profiled more often than necessary, with a correspondingly higher overhead.
When selecting a service name:
Choose a name that clearly represents the service in your application architecture. The choice of service name is less important if you only run a single service or application. It is more important if your application runs as a set of micro-services, for example.
Make sure to not use any process-specific values, like a process ID, in the service-name string.
The service-name string must match this regular expression:
^[a-z]([-a-z0-9_.]{0,253}[a-z0-9])?$
A good guideline is to use a static string like imageproc-service as the
service name.
The service version is optional. If you specify the service version, Profiler can aggregate profiling information from multiple instances and display it correctly. It can be used to mark different versions of your services as they get deployed. The Profiler UI lets you filter the data by service version; this way, you can compare the performance of older and newer versions of the code.
The value of the service-version argument is a free-form string, but values
for this argument typically look like version numbers, for example,
1.0.0 or 2.1.2.
Starting your program
Compute Engine
Start Java as you normally would to run your program, and add the the agent-configuration options:
java \
-agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myservice,-cprof_service_version=1.0.0 \
[JAVA OPTIONS] -jar PATH/TO/YOUR/JARFILE [PROGRAM OPTIONS]
GKE
Modify the service container Dockerfile to start Java as you normally would to run your program, and add the agent-configuration options:
RUN java \
-agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myservice,-cprof_service_version=1.0.0 \
[JAVA OPTIONS] -jar PATH/TO/YOUR/JARFILE [PROGRAM OPTIONS]
App Engine flexible environment
Modify the app.yaml configuration file to
set the PROFILER_ENABLE environment variable. Then start
your program as usual:
env_variables:
PROFILER_ENABLE: true
See Defining environment variables for more information.
App Engine standard environment
Modify the app.yaml or the appengine-web.xml
configuration file to include the GAE_PROFILER_MODE environment
variable to instruct Profiler to collect CPU and heap profiles,
one time per minute on average, across all instances of the same deployment:
app.yaml:
env_variables:
GAE_PROFILER_MODE: cpu,heap
appengine-web.xml:
<env-variables>
<env-var name="GAE_PROFILER_MODE" value="cpu,heap" />
</env-variables>
Then start your program as usual.
See Defining environment variables for more information.
Agent logging
The profiling agent can report logging information for App Engine flexible environment, Compute Engine, and GKE. The profiling agent supports the following logging levels:
0: Log all messages. Default logging level.1: Log warning, error, and fatal messages.2: Log error and fatal messages.3: Log only fatal messages and stop the application.
To enable writing logs to standard error with the default logging level,
append -logtostderr to the -agentpath configuration.
To set the logging level to log only error and fatal messages,
append -minloglevel=2 to the -agentpath configuration.
For example, to enable logging of error and fatal messages to standard error,
append -logtostderr and ‑minloglevel=2 to the
-agentpath configuration:
java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myapp,-logtostderr,-minloglevel=2 -jar myApp.jar
What's next
To learn about the Profiler graph and controls, go to Using the Stackdriver Profiler Interface. For advanced information, go to the following:


