Skip to main content

py_unidbg_server

py_unidbg_server is a Python-based JVM microservice that uses jpype1 to invoke Java methods from .jar files. It runs a FastAPI service via Gunicorn + Uvicorn for local calls.

The architecture is designed as a per-machine self-contained deployment, intended to be configured and run on the same machine as the client. By default, it does not rely on message queues (MQ)—clients can directly call the service locally.

In this way, the service can be combined with the machine’s original program as a single complete project, supporting one-click packaging and easy deployment without the extra configuration required by MQ-based solutions.

Advantages over the GitHub unidbg-server project:

  1. Pure Python code – no need to dive into Java Spring Boot. You only need to build your unidbg project and expose the interfaces; the microservice can integrate directly.

  2. Infinite scalability per launch – once the core unidbg libraries are loaded, new project interfaces only need their own JARs. You do not need to restart the service.

📦 Installation

From PyPI

pip install py_unidbg_server

From source

git clone https://github.com/aFunnyStrange/py_unidbg_server.git
cd py_unidbg_server
pip install -e .

🚀 Quick Start

The CLI script unidbg-server allows easy startup without needing underscores:

unidbg-server start

Notes:

  • JAR dependencies are loaded lazily: only on the first method call.
  • Once loaded, they are reused indefinitely.
  • To avoid memory growth, ensure your Java code calls .destroy() after each execution if necessary.

⚙️ Advanced Usage

If you want to customize the microservice, you can copy the core server code to your current directory:

unidbg-server edit

You can then modify the code freely for your local deployment.

🧪 Demo Project

See demo/ for an example project.

CLI Parameters: When starting the server, the following arguments control where JARs are loaded from:

-c, --core: Directory containing core JAR files (default: unidbg_core, relative to current directory). These are the core libraries needed for unidbg execution.

-p, --projects: Directory containing project JAR files (default: projects, relative to current directory). Any subdirectory inside this folder will be recursively loaded, so you do not need to place all JARs in the root.

Behavior: The service does not load JARs immediately upon startup. JARs are loaded lazily on first method invocation, and then cached and reused for all subsequent calls.

Recommended workflow:

  1. Download and package all unidbg core JARs.

  2. (Optional) Download additional dependencies such as Gson if your Java methods require JSON serialization/deserialization.

  • GitHub repository: https://github.com/google/gson

  • Maven Central: https://mvnrepository.com/artifact/com.google.code.gson/gson

  • How to get the JAR:

    1. Check the GitHub releases to find the latest version.

    2. Go to the Maven Central page and select the desired version.

    3. If the version is not listed on the page, you can directly modify the URL to download it, e.g.:

    https://repo1.maven.org/maven2/com/google/code/gson/gson/<version>/gson-<version>.jar
    
    1. Download the JAR and place it in your project folder.

    2. Add Gson to your project (Maven example):

    <dependencies>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10.1</version>
        </dependency>
    </dependencies>
    
  • Purpose: Gson is used for serializing and deserializing data when making requests to the microservice.

  • If your data contains raw bytes, you can encode them with Base64 or other encoding methods.

  • JSON is optional – you may choose another request format as long as the client and server agree on it.

  1. Create your own project, implement Java methods, and package your JAR (without core dependencies).

  2. Start the server via the CLI and make requests.

Notes: The microservice is intentionally simple – it only provides a JVM execution environment and HTTP API for Java method calls.

Documentation is minimal; for building Java projects, simply follow your IDE's packaging workflow (e.g., IntelliJ IDEA).

For reference on packaging steps, you can also check the docs/ directory included in this repository.

📄 License

This project is licensed under the BSD 3-Clause License.

Dynamic project lifecycle

Version 0.2 gives every project a dedicated JVM URLClassLoader. Core JARs remain on the process classpath, while project JARs can be drained, closed, replaced on disk, and loaded again without restarting the server.

POST   /call-java
POST   /projects/{project_name}/apis/{api_name}
GET    /projects/{project_name}/apis
GET    /list
GET    /health
DELETE /projects/{project_name}?timeout=30
POST   /projects/{project_name}/reload?timeout=30

Removal rejects new calls to that project, waits for active calls, runs an optional Java cleanup hook, and closes the loader. Timeout or cleanup failure restores the loaded state so removal can be retried. Closing the loader releases JAR handles; classes become eligible for JVM collection after project code also releases its objects, threads, callbacks, and static references.

Projects that own emulators, native handles, or executors should add projects/<name>/unidbg-project.json:

{
  "lifecycle": {
    "class": "com.example.ProjectLifecycle",
    "unload_method": "close",
    "pass_project_dir": true
  },
  "apis": {
    "sign": {
      "class": "com.example.Main",
      "method": "sign"
    },
    "decrypt": {
      "class": "com.example.Main",
      "method": "decrypt"
    }
  }
}

The hook is a public static close(String projectDirectory) method when pass_project_dir is true, or a public static close() method otherwise. It must stop project-created threads and release emulator/native resources before returning.

Every exposed method uses the simple contract public static Object method(String json). A project may expose any number of methods. Call a method directly through /call-java by adding method_name (it defaults to start), or declare stable aliases in apis and call /projects/{project}/apis/{alias}. Alias routes keep Java package/class changes out of client code.

Unidbg project development remains standalone

The server does not replace the Java project's normal development workflow. Keep a regular main entry and directly call the same exported methods while debugging in IntelliJ IDEA:

public final class Main {
    public static String sign(String json) {
        // Create/use/destroy your Unidbg emulator here.
        return "result";
    }

    public static String decrypt(String json) {
        return "plain-text";
    }

    public static void main(String[] args) {
        System.out.println(sign("{\"value\": 1}"));
        System.out.println(decrypt("{\"cipher\": \"...\"}"));
    }
}

main is only the developer test entry and is never invoked by the server. Packaging the project JAR does not require FastAPI-specific Java code or a server framework.

Deployment diagnostics

GET /list scans every directory under projects/ and reports whether each declared API really resolves to a public static Java method with exactly one String parameter. It returns the Java return type or a bounded error for each invalid class/method declaration:

[
  {
    "name": "demo",
    "loaded": false,
    "jars": ["projects/demo/project.jar"],
    "apis": [
      {
        "name": "sign",
        "class_name": "com.example.Main",
        "method_name": "sign",
        "available": true,
        "return_type": "java.lang.String",
        "error": null
      }
    ],
    "error": null
  }
]

For an unloaded project, /list creates a temporary class loader, performs reflection only, and closes it immediately. The project therefore stays lazy and its JAR is not retained by the diagnostic request. Reflection confirms the class and method contract without executing business code; runtime data or emulator failures can only be observed by calling the API itself. Projects that do not declare apis remain visible with an empty API list.

Lifecycle state is local to one Python process, so the CLI currently requires --workers 1. Scale horizontally with separate server instances and broadcast lifecycle operations through a coordinator/control plane.

Python API

HTTP is optional; direct callers can use the stable export surface:

from py_unidbg_server import call_java, configure, inspect_projects, unload_project

configure("./unidbg_core", "./projects")
result = call_java(
    "demo",
    "com.example.Main",
    '{"value": 1}',
    method_name="sign",
)
unload_project("demo", timeout=30)
diagnostics = inspect_projects()

See docs/architecture.md for the module boundaries and extension rules.

Validation

pip install -e ".[dev]"
pytest -q

When JDK tools are installed, the system test compiles disposable v1/v2 JARs and verifies invocation, cleanup, loader close, replacement, and reload in the same JVM.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py_unidbg_server-0.2.0.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_unidbg_server-0.2.0-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

Details for the file py_unidbg_server-0.2.0.tar.gz.

File metadata

  • Download URL: py_unidbg_server-0.2.0.tar.gz
  • Upload date:
  • Size: 22.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for py_unidbg_server-0.2.0.tar.gz
Algorithm Hash digest
SHA256 de994d5e8870eca882312f85c506cf11ce9cefa7799630ce0a796f057f83cac5
MD5 03f98ed3fb08388bd12059011303ae3b
BLAKE2b-256 4aae39449403fa2938258bade8ff895eb69aae179532dcaba7131513115dad77

See more details on using hashes here.

File details

Details for the file py_unidbg_server-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for py_unidbg_server-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0182f97b3fd470cce204d67f74a0775cb279991d157637fe534017647926e190
MD5 f826394483737fa18adf8d54191473b8
BLAKE2b-256 821fd1bb7b6027f7551f090f8ea13164fefe18c16c0f55ddf181fea29a75eeda

See more details on using hashes here.

Release history Release notifications | RSS feed

1.0.0

2 files

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page