---
title: "pyroscope.java | Grafana Alloy documentation"
description: "Learn about pyroscope.java"
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# `pyroscope.java`

`pyroscope.java` continuously profiles Java processes running on the local Linux OS using [async-profiler](https://github.com/async-profiler/async-profiler).

> Note
> 
> To use the `pyroscope.java` component you must run Alloy as root and inside host PID namespace.

You can specify multiple `pyroscope.java` components by giving them different labels.

## Usage

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
pyroscope.java "<LABEL>" {
  targets    = <TARGET_LIST>
  forward_to = <RECEIVER_LIST>
}
```

## Target JVM configuration

When you use `pyroscope.java` to profile Java applications, you can configure the target JVMs with some command line flags that ensure accurate profiling, especially for inlined methods. Add the following flags to your Java application’s startup command:

java ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```java
-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints
```

For more details, refer to [Restrictions/Limitations](https://github.com/async-profiler/async-profiler?tab=readme-ov-file#restrictionslimitations) in the async-profiler documentation.

## Additional configuration for Linux capabilities

If your Kubernetes environment has Linux capabilities enabled, configure the following in your Helm values to ensure `pyroscope.java` functions properly:

YAML ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```yaml
alloy:
  securityContext:
    runAsUser: 0
    runAsNonRoot: false
    capabilities:
      add:
        - PERFMON
        - SYS_PTRACE
        - SYS_RESOURCE
        - SYS_ADMIN
```

These capabilities enable Alloy to access performance monitoring subsystems, trace processes, override resource limits, and perform necessary system administration tasks for profiling.

> Note
> 
> Adjust capabilities based on your specific security requirements and environment, following the principle of least privilege. The capability behavior depends on Container Runtime Interface (CRI) settings. For example, Docker drops capabilities that aren’t on the allowlist by default.

## Arguments

You can use the following arguments with `pyroscope.java`:

Expand table

| Name         | Type                     | Description                                      | Default  | Required |
|--------------|--------------------------|--------------------------------------------------|----------|----------|
| `forward_to` | `list(ProfilesReceiver)` | List of receivers to send collected profiles to. |          | yes      |
| `targets`    | `list(map(string))`      | List of java process targets to profile.         |          | yes      |
| `tmp_dir`    | `string`                 | Temporary directory to store async-profiler.     | `"/tmp"` | no       |

After component startup, `pyroscope.java` creates a temporary directory under the `tmp_dir` argument and extracts the async-profiler binaries for both `glibc` and `musl` into the directory with the following layout.

text ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```text
/tmp/alloy-asprof-glibc-{SHA1}/bin/asprof
/tmp/alloy-asprof-glibc-{SHA1}/lib/libasyncProfiler.so
/tmp/alloy-asprof-musl-{SHA1}/bin/asprof
/tmp/alloy-asprof-musl-{SHA1}/lib/libasyncProfiler.so
```

After process profiling startup, the component detects `libc` type and copies the matching `libasyncProfiler.so` into the target process’s file system at the exact same path.

> Note
> 
> The `asprof` binary runs with root permissions. If you change the `tmp_dir` argument to something other than `/tmp`, then you must ensure that the directory is only writable by root.
> 
> The filesystem mounted at `tmp_dir` in the Alloy and target containers must allow file execution. A mount option such as `noexec` prevents this.

Each target in the `targets` argument must always include the special `__process_pid__` label, which corresponds to the process PID that’s used for profiling.

> Warning
> 
> `pyroscope.java` doesn’t fail or report unhealthy if a target is missing the `__process_pid__` label. It logs an error and silently skips profiling that target instead.

The component treats labels that start with a double underscore as *internal* and removes them before scraping.

Every profile carries a `service_name` label. You can set it on the target yourself. If you don’t, `pyroscope.java` adds the label and infers a value from the following sources, in this order:

1. `__meta_kubernetes_pod_annotation_pyroscope_io_service_name` which is a `pyroscope.io/service_name` Pod annotation.
2. `__meta_kubernetes_namespace` and `__meta_kubernetes_pod_container_name`, combined into `java/<namespace>/<container_name>`.
3. `__meta_docker_container_name`
4. `__meta_dockerswarm_container_label_service_name` or `__meta_dockerswarm_service_name`

When you don’t set `service_name` and the component can’t infer a value, it uses `unspecified`.

### Injected labels

Independently of the `targets` argument, `pyroscope.java` automatically injects the following labels into collected profiles if you haven’t already defined them:

Expand table

| Label                | Description                                                                |
|----------------------|----------------------------------------------------------------------------|
| `otel.scope.name`    | The instrumentation scope name, set to `com.grafana.alloy/pyroscope.java`. |
| `otel.scope.version` | The Alloy version that produced the profile.                               |

Alloy only sets `otel.scope.name` and `otel.scope.version` if they aren’t already present on the profile. `otel.scope.version` is only set when `otel.scope.name` matches the default value.

## Blocks

You can use the following block with `pyroscope.java`:

No valid configuration blocks found.

### `profiling_config`

The `profiling_config` block describes how the component invokes async-profiler.

You can use the following arguments with the `profiling_config` block:

Expand table

| Name               | Type           | Description                                                                                                                         | Default    | Required |
|--------------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------|------------|----------|
| `alloc`            | `string`       | Allocation profiling sampling configuration. It’s passed as an `--alloc` argument to async-profiler.                                | `"512k"`   | no       |
| `cpu`              | `bool`         | A flag to enable CPU profiling, using `itimer` async-profiler event by default.                                                     | `true`     | no       |
| `custom_arguments` | `list(string)` | Sends raw args to async-profiler, skipping all Alloy arguments except `interval`. Refer to [`custom_arguments`](#custom_arguments). | `[]`       | no       |
| `event`            | `string`       | Sets the CPU profiling event. Refer to [`event`](#event) for supported values.                                                      | `"itimer"` | no       |
| `interval`         | `duration`     | How frequently to collect profiles from the targets.                                                                                | `"60s"`    | no       |
| `lock`             | `string`       | Lock profiling sampling configuration. It’s passed as an `--lock` argument to async-profiler.                                       | `"10ms"`   | no       |
| `log_level`        | `string`       | Sets the log level in async profiler. One of `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, or `NONE`.                                  | `"INFO"`   | no       |
| `per_thread`       | `bool`         | Sets per thread mode on async profiler. It’s passed as an `-t` argument to async-profiler.                                          | `false`    | no       |
| `quiet`            | `bool`         | If set, suppresses the `Profiling started/stopped` log message.                                                                     | `false`    | no       |
| `sample_rate`      | `int`          | CPU profiling sample rate. It’s converted from Hz to interval and passed as an `-i` argument to async-profiler.                     | `100`      | no       |
| `tlab`             | `bool`         | Enables TLAB-based allocation events. Passed as `--tlab` to async-profiler. Requires `alloc`.                                       | `false`    | no       |

Refer to [profiler-options](https://github.com/async-profiler/async-profiler?tab=readme-ov-file#profiler-options) for more information about async-profiler configuration.

### `custom_arguments`

`custom_arguments` passes async-profiler `start` flags directly.

When you set `custom_arguments`, Alloy skips these options from this block:

`cpu`, `event`, `per_thread`, `sample_rate`, `alloc`, `lock`, `log_level`, `tlab`.

For example, this configuration enables multi-event profiling for `cpu`, `alloc`, and `lock` with custom thresholds:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
pyroscope.java "java" {
  targets    = discovery.relabel.java.output
  forward_to = [pyroscope.write.staging.receiver]

  profiling_config {
    interval = "60s"
    custom_arguments = ["-e", "cpu,alloc,lock", "--alloc", "2m", "--lock", "10ms"]
  }
}
```

Refer to [Profiling modes](https://github.com/async-profiler/async-profiler/blob/master/docs/ProfilingModes.md) and [profiler-options](https://github.com/async-profiler/async-profiler?tab=readme-ov-file#profiler-options) for the complete async-profiler option list.

### `event`

The `event` argument configures the profiling mode used by async-profiler. async-profiler supports various profiling modes including CPU profiling, wall-clock profiling, and hardware performance monitoring events. For a complete overview of all available profiling modes and their use cases, refer to [Profiling modes](https://github.com/async-profiler/async-profiler/blob/master/docs/ProfilingModes.md) in the async-profiler documentation.

### `per_thread`

> Warning
> 
> The `per_thread` option doesn’t apply when using JFR output format. Since `pyroscope.java` uses JFR format exclusively, this option has no effect. For more details, refer to [Options applicable to any output format except JFR](https://github.com/async-profiler/async-profiler/blob/master/docs/ProfilerOptions.md#options-applicable-to-any-output-format-except-jfr) in the async-profiler documentation.

## Exported fields

`pyroscope.java` doesn’t export any fields.

## Component health

`pyroscope.java` is only reported as unhealthy if given an invalid configuration. In those cases, exported fields retain their last healthy values.

## Debug information

`pyroscope.java` doesn’t expose any component-specific debug information.

## Debug metrics

`pyroscope.java` doesn’t expose any component-specific debug metrics.

## Example

The following example profiles every Java process on the current host:

Alloy ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```alloy
pyroscope.write "staging" {
  endpoint {
    url = "http://localhost:4040"
  }
}

discovery.process "all" {
  refresh_interval = "60s"
  discover_config {
    cwd = true
    exe = true
    commandline = true
    username = true
    uid = true
    container_id = true
  }
}

discovery.relabel "java" {
  targets = discovery.process.all.targets
  rule {
    action = "keep"
    regex = ".*/java$"
    source_labels = ["__meta_process_exe"]
  }
}

pyroscope.java "java" {
  targets = discovery.relabel.java.output
  forward_to = [pyroscope.write.staging.receiver]
  profiling_config {
    interval = "60s"
    alloc = "512k"
    cpu = true
    sample_rate = 100
    lock = "1ms"
  }
}
```

## Compatible components

`pyroscope.java` can accept arguments from the following components:

- Components that export [Targets](../../../compatibility/#targets-exporters)
- Components that export [Pyroscope `ProfilesReceiver`](../../../compatibility/#pyroscope-profilesreceiver-exporters)

> Note
> 
> Connecting some components may not be sensible or components may require further configuration to make the connection work correctly. Refer to the linked documentation for more details.
