All Products
Search
Document Center

Application Real-Time Monitoring Service:Monitor JVM applications with Managed Service for Prometheus

Last Updated:Mar 10, 2026

When you run Java applications on Container Service for Kubernetes (ACK), you need visibility into heap memory, garbage collection (GC), threads, and class loading to diagnose performance issues. Managed Service for Prometheus collects these JVM metrics from your applications and makes them available in Grafana dashboards with alerting support.

The following procedure covers instrumenting a Spring Boot application with the Prometheus client library, deploying it to ACK, configuring Prometheus to scrape the metrics, and viewing the results in Grafana.

How it works

The monitoring pipeline has four stages:

  1. Instrument -- Add the Prometheus client library to your JVM application so it exposes metrics on an HTTP endpoint.

  2. Deploy -- Build a container image, push it to Container Registry, and deploy the application to an ACK cluster.

  3. Scrape -- Configure a ServiceMonitor in Managed Service for Prometheus to discover and scrape the metrics endpoint automatically.

  4. Visualize -- View the collected JVM metrics in a Managed Service for Grafana dashboard and create alert rules.

Flowchart

JVM metrics collected

The simpleclient_hotspot library exposes standard JVM metrics in the following categories:

CategoryExample metricsDescription
Memoryjvm_memory_bytes_used, jvm_memory_bytes_committed, jvm_memory_bytes_maxHeap and non-heap memory usage in bytes
Garbage collectionjvm_gc_collection_seconds_count, jvm_gc_collection_seconds_sumGC invocation count and cumulative time per collector
Threadsjvm_threads_current, jvm_threads_daemon, jvm_threads_peakActive, daemon, and peak thread counts
Classesjvm_classes_loaded, jvm_classes_loaded_total, jvm_classes_unloaded_totalCurrently loaded and historically loaded/unloaded class counts

Prerequisites

Before you begin, make sure that you have:

Sample project

A complete sample project is available on GitHub. The file paths referenced below correspond to that repository.

Step 1: Instrument the JVM application

Add the Prometheus client library to your Spring Boot application so it exposes JVM metrics on a dedicated HTTP endpoint.

  1. Add the simpleclient_hotspot dependency to pom.xml.

       <dependency>
           <groupId>io.prometheus</groupId>
           <artifactId>simpleclient_hotspot</artifactId>
           <version>0.6.0</version>
       </dependency>
  2. Register the default JVM metrics collectors by adding the following method to your controller class. DefaultExports.initialize() registers collectors for memory pools, GC, threads, and class loading. The @PostConstruct annotation runs this method once at application startup. See /src/main/java/com/monitise/prometheus_demo/DemoController.java in the sample project.

       @PostConstruct
           public void initJvmExporter() {
               io.prometheus.client.hotspot.DefaultExports.initialize();
           }
  3. Configure the metrics port and path in application.properties. Port 8081 serves metrics separately from the application port (8080). The path /prometheus-metrics is where Prometheus sends scrape requests. See /src/main/resources/application.properties in the sample project.

       management.port: 8081
       endpoints.prometheus.path: prometheus-metrics
  4. Enable the Prometheus endpoint in the main application class. @EnablePrometheusEndpoint exposes the /prometheus-metrics endpoint. @EnableSpringBootMetricsCollector exports Spring Boot actuator metrics in Prometheus format. See /src/main/java/com/monitise/prometheus_demo/PrometheusDemoApplication.java in the sample project.

       @SpringBootApplication
       // sets up the prometheus endpoint /prometheus-metrics
       @EnablePrometheusEndpoint
       // exports the data at /metrics at a prometheus endpoint
       @EnableSpringBootMetricsCollector
       public class PrometheusDemoApplication {
           public static void main(String[] args) {
               SpringApplication.run(PrometheusDemoApplication.class, args);
           }
       }

Step 2: Build and push the container image

Package the instrumented application as a Docker image and push it to Container Registry.

  1. Compile the project.

       mvn clean install -DskipTests
  2. Build the Docker image. Example:

       docker build -t <image-name>:<tag> . --no-cache
       docker build -t promethues-demo:v0 . --no-cache
  3. Tag the image for Container Registry. Example:

       sudo docker tag <image-name>:<tag> <registry-domain>/<namespace>/<image-name>:<tag>
       sudo docker tag promethues-demo:v0 registry.cn-hangzhou.aliyuncs.com/testnamespace/promethues-demo:v0
  4. Push the image to Container Registry. Example:

       sudo docker push <registry-domain>/<namespace>/<image-name>:<tag>
       sudo docker push registry.cn-hangzhou.aliyuncs.com/testnamespace/promethues-demo:v0
  5. Verify the upload. Open the Container Registry console, navigate to your repository, and confirm the image appears on the Tags page.

    Image

Replace the placeholders with your values:

PlaceholderDescriptionExample
<image-name>Docker image namepromethues-demo
<tag>Image version tagv0
<registry-domain>Container Registry endpointregistry.cn-hangzhou.aliyuncs.com
<namespace>Container Registry namespacetestnamespace

Step 3: Deploy to the ACK cluster

Deploy the JVM application to your ACK cluster and expose it as a Kubernetes Service.

Create the Deployment

  1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

  2. On the Clusters page, find your cluster and click its name. In the left-side pane, choose Workloads > Deployments.

  3. On the Deployments page, click Create from YAML in the upper-right corner and enter the following YAML: The three prometheus.io/* annotations tell Managed Service for Prometheus how to discover and scrape this application: The Deployment runs two replicas. Each pod exposes port 8080 for application traffic and port 8081 for the Prometheus metrics endpoint. Example with concrete values: After you create the Deployment, the pods appear on the Deployments page.

    AnnotationPurpose
    prometheus.io/scrape: 'true'Marks the pod as a scrape target
    prometheus.io/path: '/prometheus-metrics'HTTP path where metrics are exposed
    prometheus.io/port: '8081'Port to scrape (the management port from Step 1)
       apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
       kind: Deployment
       metadata:
         name: prometheus-demo
       spec:
         replicas: 2
         template:
           metadata:
             annotations:
               prometheus.io/scrape: 'true'
               prometheus.io/path: '/prometheus-metrics'
               prometheus.io/port: '8081'
             labels:
               app: tomcat
           spec:
             containers:
             - name: tomcat
               imagePullPolicy: Always
               image: <registry-domain>/<namespace>/<image-name>:<tag>
               ports:
               - containerPort: 8080
                 name: tomcat-normal
               - containerPort: 8081
                 name: tomcat-monitor
       apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
       kind: Deployment
       metadata:
         name: prometheus-demo
         labels:
           app: tomcat
       spec:
         replicas: 2
         selector:
           matchLabels:
             app: tomcat
         template:
           metadata:
             annotations:
               prometheus.io/scrape: 'true'
               prometheus.io/path: '/prometheus-metrics'
               prometheus.io/port: '8081'
             labels:
               app: tomcat
           spec:
             containers:
             - name: tomcat
               imagePullPolicy: Always
               image: registry.cn-hangzhou.aliyuncs.com/peiyu-test/prometheus-demo:v0
               ports:
               - containerPort: 8080
                 name: tomcat-normal
               - containerPort: 8081
                 name: tomcat-monitor

    Container group

Create the Service

  1. In the left-side navigation pane, choose Network > Services.

  2. On the Services page, click Create Resources in YAML.

  3. On the Create page, enter the following YAML in the Template code editor and click Create: This NodePort Service exposes both the application port (8080) and the metrics port (8081), making the metrics endpoint reachable by Managed Service for Prometheus. After you create the Service, it appears on the Services page.

       apiVersion: v1
       kind: Service
       metadata:
         labels:
           app: tomcat
         name: tomcat
         namespace: default
       spec:
         ports:
         - name: tomcat-normal
           port: 8080
           protocol: TCP
           targetPort: 8080
         - name: tomcat-monitor
           port: 8081
           protocol: TCP
           targetPort: 8081
         type: NodePort
         selector:
           app: tomcat

    Service

Step 4: Configure service discovery

Configure a ServiceMonitor in Managed Service for Prometheus to automatically discover and scrape the JVM metrics endpoint. For detailed instructions, see Use ServiceMonitors to discover and monitor Services.

Verify the setup

After you complete all four steps, confirm that JVM metrics flow into Prometheus:

  1. Open the Managed Service for Prometheus console and navigate to your ACK cluster.

  2. On the Targets page, verify that your application pods appear as active scrape targets with a status of UP.

  3. Open a Grafana dashboard and run a query such as jvm_memory_bytes_used to confirm data is flowing.

Troubleshooting

If metrics do not appear, check the following:

SymptomPossible causeResolution
Targets not listedPod annotations missing or incorrectVerify that prometheus.io/scrape, prometheus.io/path, and prometheus.io/port in the Deployment YAML match the port and path configured in application.properties.
Target status is DOWNMetrics endpoint unreachableMake sure port 8081 is not blocked by network policies in the cluster. Confirm the application started and the endpoint returns data by running curl http://<pod-ip>:8081/prometheus-metrics from within the cluster.
Metrics exist but dashboard is emptyGrafana data source misconfiguredVerify that the Grafana data source points to the correct Managed Service for Prometheus instance and that the query uses the correct metric name (for example, jvm_memory_bytes_used).

What to do next

  • Set up a Grafana dashboard -- Community dashboard templates such as JVM (Micrometer) or JVM (Prometheus) provide a ready-made starting point for visualizing JVM metrics.

  • Create alert rules -- Configure alerts for heap memory usage, long GC pauses, or thread count spikes. For more information, see the alert configuration documentation for Managed Service for Prometheus.