# jvm-sandbox: runtime AOP for a JVM you cannot restart

> Alibaba's JVM-SANDBOX attaches to a running Java process and weaves method-level AOP without touching the application. Here is how the classloader isolation, the Spy bridge and the module lifecycle actually work, and where the tool stops being the right answer.

**alibaba/jvm-sandbox** — Real - time non-invasive AOP framework container based on JVM

- Repository: https://github.com/alibaba/jvm-sandbox
- Stars: 6,958 · Forks: 1,586
- Language: Java
- License: LGPL-3.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/alibaba-jvm-sandbox

## The problem jvm-sandbox solves: AOP on a JVM you are not allowed to restart

Most AOP in Java is decided before the process starts. Static weaving writes advice into bytecode at build time. Spring AOP applies proxies to beans the container manages. CGLIB-style dynamic weaving renames the original method and generates a same-signature proxy, which means the target class has to be modified and the proxy is fixed once the application is up. The README names both of those boundaries directly: invasiveness, because the target class must be altered (a Spring bean has to live in the container), and fixation, because a method enhanced at startup cannot be re-enhanced later.

The audience the README describes is not the average application developer. It is the engineer who gets a production complaint, has no logs with the argument values needed to reproduce it, and cannot add a log line and redeploy. The README lists the motivations in the first person: wanting dynamic logging filtered by business ID, wanting to simulate an in-process exception rather than only an inter-service one, and wanting line-level call-chain data for coverage analysis. The last motivation is the architectural one. If you build a recorder, a fault injector and a dynamic logger separately, they share the same underlying bytecode mechanism, and the README asks how you keep them from interfering with each other, how you load and unload them dynamically, and how you restore the original code when one of them misbehaves. jvm-sandbox is the answer to that last question: a container for those tools, not the tools themselves.

## BEFORE, RETURN and THROWS: the event model behind the weaving

The sandbox decomposes any Java method invocation into three points. BEFORE is entry, RETURN is a normal return, THROWS is a thrown exception. The README shows this as a try/catch skeleton with each label marking where a probe fires. A module registers interest in a class and method, and the container reports at those three points.

What a module can do at each point is the substance of the design. At BEFORE it can read and change the arguments. At RETURN it can read and change the returned value, or turn a return into a thrown exception. At THROWS it can read the exception and replace it, or convert the failure into a normal return. The most consequential capability is short-circuiting: returning a custom result at BEFORE means the original method body never runs. That is the mechanism behind in-process fault simulation, and it is also the mechanism most likely to produce a confusing production incident if a module is careless.

The constraint that shapes all of this is the JDK's own rule for redefining a class at runtime, which the README states explicitly: you may not add, modify or delete fields, you may not add or delete methods, and you may not change method signatures. A weaving framework that ignored those rules would simply fail on the target JVM. jvm-sandbox's claim is that its bytecode construction stays inside them, which is why it can call itself non-invasive. The README does not publish the transformation details, so if you need to reason about a specific method shape, the wiki is the place to look rather than the README.

## Classloader isolation and the Spy class: why the target application never sees the sandbox

Two mechanisms keep the sandbox from polluting the application. The first is SandboxClassLoader, which the README says deliberately breaks the parent-delegation convention so that sandbox classes and application classes do not resolve through the same chain. The second is ModuleJarClassLoader, which gives each module its own loader, so modules are isolated from each other, from the sandbox core, and from the application. The repository layout matches that story: sandbox-core, sandbox-api, sandbox-common-api, sandbox-provider-api, sandbox-module-starter and sandbox-spy are separate modules, and the README notes that sandbox, sandbox-api, sandbox-common-api, sandbox-module-starter and sandbox-provider-api are the artifacts installed to the local Maven repository by mvn clean install.

The Spy class is the piece that makes the isolation workable. According to the README, the sandbox buries a Spy class inside BootstrapClassLoader, and that class carries the communication between the enhanced target classes and the sandbox kernel. The reason is a classloader visibility problem: instrumented bytecode injected into an application class has to call back into sandbox code, but the application's loader cannot see the sandbox's loader. Putting the bridge in the bootstrap loader makes it visible from everywhere. The README does not document what happens if another agent has already placed a class with the same name in the bootstrap loader, which is the kind of collision worth testing before you deploy this alongside a second Java agent.

## Installing jvm-sandbox and attaching to a running process

The README gives two routes: download a release archive, or build one yourself. The download command points at an OSS URL, and the README warns in the comment that the OSS may have expired or become unreachable, in which case you package it yourself.

```bash
wget https://ompc.oss-cn-hangzhou.aliyuncs.com/jvm-sandbox/release/sandbox-1.3.3-bin.zip
unzip sandbox-1.3.3-bin.zip
```

If you go the self-build route, the README's script directory is bin, and the output lands in target with several artifact types to choose from.

```bash
cd bin
./sandbox-packages.sh
cd ../target
```

Two build constraints are stated in the README and they are not optional. You must build with JDK 1.8, because the project and its Maven plugins use tools.jar. You must build on Linux, Mac or Unix, because some test cases do not handle the $USER_HOME path on Windows. That second point is a real limitation, not a footnote: if your build machine is Windows, the project's own test suite is documented as failing there.

Attaching is a single command against a process ID. The README uses 33342 as the example target.

```bash
cd sandbox/bin
./sandbox.sh -p 33342
```

A successful attach prints a status block. The README's example shows the fields you should expect, including NAMESPACE, VERSION, MODE (ATTACH), SERVER_ADDR, SERVER_PORT, UNSAFE_SUPPORT, SANDBOX_HOME, SYSTEM_MODULE_LIB, USER_MODULE_LIB, SYSTEM_PROVIDER_LIB and EVENT_POOL_SUPPORT. If that block does not appear, the attach did not succeed, and nothing downstream will work. Unloading is the same script with -S.

```bash
./sandbox.sh -p 33342 -S
```

The README shows the expected output as a shutdown confirmation line. Whether the target application returns to a byte-for-byte identical state is not something the README documents, and that is the first thing to verify in a staging process before you attach to anything that matters.

## Building a module, and the boundary the README does not draw

The README describes the module lifecycle as pluggable: modules load and unload without leaving traces in the target application. It does not walk through writing one. What the repository layout tells you is where to start: sandbox-api and sandbox-common-api are the interfaces a module compiles against, sandbox-module-starter is the scaffolding, and sandbox-provider-api covers providers. The README confirms that mvn clean install places those artifacts in the local Maven repository, which is the step that makes a module project compile.

```bash
mvn clean install
```

That gap matters for evaluation. A reader arriving from the README's scenario list (fault simulation, record and replay, dynamic logging, line-level call chains) might expect those to be features of the sandbox. They are not. The README frames them as tools you would build on top, and explains the project's own origin story as a deliberate choice to be a lower layer rather than an all-in-one platform. The repository does ship sandbox-debug-module and sandbox-mgr-module, but the README does not document what either one does, so treat them as things to inspect in the source rather than as a product surface. Version numbering is another detail worth knowing before you fork: the README says a version bump touches every pom file plus the version resource under sandbox-core, and provides bin/set-version.sh with an s or r first argument to mark a snapshot or a release.

## Where jvm-sandbox is the wrong choice

The JDK support range is the hardest boundary. The README states support for JDK 6 through 11. Modern applications on later JDKs are outside the documented range, and because the whole mechanism depends on runtime class redefinition plus a bootstrap-loaded Spy class, that is not a range you can assume extends by itself. If your fleet has moved past JDK 11, this project's documented target is behind you.

The build toolchain is the second constraint. Requiring JDK 1.8 for the build because of tools.jar means the project's own build cannot run on a newer JDK, even if the artifact it produces can attach to a JDK 11 process. That split between build JDK and target JDK is easy to get wrong in CI.

The third boundary is conceptual. If your instrumentation can be decided at build time, static weaving is simpler and has no runtime attach step, no bootstrap class, and no unload semantics to reason about. If your beans are all Spring-managed and you only need method interception around them, Spring AOP already covers it without a sandbox. jvm-sandbox earns its complexity specifically when the process is already running and you are not allowed to touch it.

Finally, the README does not document rollback guarantees, conflict behaviour with other Java agents, or the performance cost of an active module. Those are the questions that decide a production deployment, and the README is silent on all three.

## How jvm-sandbox differs from BTRACE and from compile-time weaving

The README names BTRACE as the project's inspiration and explicitly contrasts the intent: BTRACE is described as powerful, and the stated motivation was to build something more convenient and better suited to the author's own problem-locating needs, covering both online link monitoring and single-machine diagnosis. The practical difference is scope. BTRACE is a tracing tool you point at a JVM to get output. jvm-sandbox is a container that hosts modules, with a namespace, a server port, a module library directory and a provider directory visible in the attach banner. One gives you a script; the other gives you a runtime to load many scripts into, side by side, and unload again.

Against compile-time weaving and Spring AOP the difference is when the decision is made. Static weaving and container-managed proxies decide at build or startup, and the README's critique of CGLIB-style dynamic weaving applies to both: the target class is touched, and the enhancement is fixed once running. jvm-sandbox moves the decision to attach time and keeps it reversible through unload. The trade is that you inherit a classloader architecture, a bootstrap Spy class, and the JDK 6 to 11 range, none of which a build-time weaver asks of you.

The related-search data shows people also look for jvm-sandbox under the terms jvm sandbox repeater and jvm sandbox mock. The README does list method request recording with result replay and fault simulation as scenarios, but it presents them as things built on the container, not as commands the sandbox ships. If you arrive expecting a ready-made repeater, you will be building it.

## Licence and the cost of staying current

The repository carries LGPL-3.0, with LICENSE and COPYING.LESSER at the top level. That is a copyleft licence with a linking exception tradition, and it is a different proposition from the Apache-2.0 licence many Alibaba Java projects use. If you plan to ship a modified sandbox inside a proprietary product, or to statically link its code into your own module, the licence terms are the thing to read first. This is not legal advice; the point is that LGPL-3.0 changes the calculus for embedding, and it is worth a review before your module design hardens around these APIs.

On maintenance, the release history is the useful signal. The most recent release listed is 1.4.0 from 2023-01-26, preceded by 1.3.3 in 2020-07-07 and 1.3.2 in 2020-06-17. The last push to the default branch was on 2026-09-09, so the repository is not dormant, but the release cadence is slow: three releases across six years. For an adopter that means the API you build against is likely to be stable, and also that a fix you need may sit on master rather than in a tagged artifact. Budget for building from source rather than waiting on a release, and note the README's own warning that the download OSS link may be unavailable, which pushes you toward the self-build path anyway. The README also does not publish a compatibility policy for modules across sandbox versions, so pin the version you build against and test the upgrade explicitly.

## Conclusion

Adopt jvm-sandbox when the process you need to instrument cannot be restarted and you can accept JDK 6 to 11 plus a JDK 1.8 build toolchain. Do not adopt it if you only need compile-time instrumentation, if your target runs on a JDK outside that range, or if you expect the project to hand you ready-made fault-injection and record-replay tools rather than a container to build them in. Before writing any module, verify three things against your own environment: that sandbox.sh -p <pid> prints the NAMESPACE and SERVER_PORT banner on the target JVM, that your module jar loads through ModuleJarClassLoader without pulling in application classes, and that ./sandbox.sh -p <pid> -S leaves the process in the state you found it.

## FAQ

### What is jvm-sandbox in Java?

It is a JVM container for real-time, non-invasive AOP, described in the README as an AOP solution that works on a running JVM without restarting or modifying the target application. It attaches to a process, weaves method-level interception, and hosts pluggable modules that can be loaded and unloaded.

### How do I install and attach jvm-sandbox to a running JVM?

The README offers a release archive download and a self-build path through bin/sandbox-packages.sh. Once unpacked, you run ./sandbox.sh -p <pid> from the sandbox/bin directory, and a successful attach prints a banner with fields such as NAMESPACE, VERSION, MODE, SERVER_ADDR and SERVER_PORT.

### Which JDK versions does jvm-sandbox support?

The README states support for JDK 6 through 11. Separately, the build itself must run on JDK 1.8 because the project and its Maven plugins use tools.jar, and it must run on Linux, Mac or Unix because some test cases do not handle Windows $USER_HOME paths.

### Does jvm-sandbox include a repeater or fault-injection tool?

No. The README lists method recording with result replay and fault simulation as application scenarios, and describes the project as a lower layer that other tools are built on, not an all-in-one platform. The repository does contain sandbox-debug-module and sandbox-mgr-module, but the README does not document what they do.

### How does jvm-sandbox avoid interfering with the target application's classes?

It uses a custom SandboxClassLoader that breaks the parent-delegation convention to separate sandbox classes from application classes, and a ModuleJarClassLoader that isolates each module from the others, from the sandbox core and from the application. A Spy class placed in BootstrapClassLoader carries the communication between enhanced target classes and the sandbox kernel.

## Sources

- [alibaba/jvm-sandbox on GitHub](https://github.com/alibaba/jvm-sandbox)
- [Issues](https://github.com/alibaba/jvm-sandbox/issues)
- [License: LGPL-3.0](https://github.com/alibaba/jvm-sandbox/blob/master/LICENSE)
- [README](https://github.com/alibaba/jvm-sandbox/blob/master/README.md)
- [Releases](https://github.com/alibaba/jvm-sandbox/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/alibaba-jvm-sandbox
