risingwavelabs/risingwave · critical · anyhow
fail to new JVM
Error message
fail to new JVM
What it means
JavaVM::new failed to create the Java virtual machine after the JNI args (classpath, options, etc.) were built. The detailed JNI error is logged, and a generic `fail to new JVM` error is returned. Common causes are a missing/incompatible libjvm, wrong JAVA_HOME, bad JVM options, or insufficient memory.
Solutions
- Check the error log line `fail to new JVM` for the underlying JNI error code.
- Verify JAVA_HOME points to a full JDK (e.g. Java 11/17 as required) with lib/.../libjvm.so present.
- Set LD_LIBRARY_PATH to include $JAVA_HOME/lib/server so libjvm.so loads.
- Review CONNECTOR_LIBS_PATH/jvm options for invalid -X flags or garbage values.
- Confirm enough memory exists (JVM heap options not exceeding container limits).
Example fix
// before # no JAVA_HOME, only a JRE installed // after export JAVA_HOME=/usr/lib/jvm/java-17-openjdk && export LD_LIBRARY_PATH=$JAVA_HOME/lib/server:$LD_LIBRARY_PATH
Defensive patterns
Strategy: try-catch
Validate before calling
test -n "$JAVA_HOME" && test -f "$JAVA_HOME/lib/server/libjvm.so" && echo 'JVM OK' || echo 'JAVA_HOME missing or libjvm.so not found'
Try / catch
match jvm_runtime::global_jvm() {
Err(e) if e.to_string().contains("fail to new JVM") => {
// check JAVA_HOME, LD_LIBRARY_PATH, JDK version, then surface a clear ops message
}
other => other?,
} Prevention
- Pin the required JDK version in the deployment image and CI.
- Export JAVA_HOME and include $JAVA_HOME/lib/server in LD_LIBRARY_PATH.
- Validate JVM -X options against container memory limits.
- Smoke-test JVM startup in a preflight step before launching the connector.
When it happens
Trigger: Calling build_jvm_with_native_registration when libjvm.so cannot be found/loaded, an invalid JVM option string is passed via JNI args, or the JDK version is incompatible with the expected one (e.g. Java 11 vs 17).
Common situations: JAVA_HOME unset or pointing at a JRE instead of a JDK, CONNECTOR_LIBS_PATH containing an incompatible JDK, missing libjvm.so on the loader path (LD_LIBRARY_PATH), containers without a JVM installed.
Related errors
- argument `--license-key-path` (or env var…
- Caught Java Exception
- Input object is not a java string and can't be converted!
- adlsgen2.authority_host does not parse as a URL
- adlsgen2.authority_host must not contain a path component
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/a6c3768427eb2ca9.
Report an issue: GitHub.
Appendix: source
Thrown at src/jni_core/src/jvm_runtime.rs:123
// Exit the embedded JVM on uncaught `OutOfMemoryError` so that the host
// compute node process terminates and the cluster recovers via the standard
// recovery loop, matching native OOM behavior. Set `JVM_EXIT_ON_OOM=false`
// (or `0`) to opt out.
let exit_on_oom = std::env::var("JVM_EXIT_ON_OOM")
.map(|v| !matches!(v.to_ascii_lowercase().as_str(), "false" | "0" | ""))
.unwrap_or(true);
if exit_on_oom {
args_builder = args_builder.option("-XX:+ExitOnOutOfMemoryError");
}
tracing::info!("JVM args: {:?}", args_builder);
let jvm_args = args_builder.build().context("invalid jvm args")?;
// Create a new VM
let jvm = match JavaVM::new(jvm_args) {
Err(err) => {
tracing::error!(error = ?err.as_report(), "fail to new JVM");
bail!("fail to new JVM");
}
Ok(jvm) => jvm,
};
tracing::info!("initialize JVM successfully");
let result: std::result::Result<(), jni::errors::Error> = try {
let mut env = jvm_env(&jvm)?;
register_java_binding_native_methods(&mut env)?;
};
result.context("failed to register native method")?;
Ok(jvm)
}
pub fn jvm_env(jvm: &JavaVM) -> Result<AttachGuard<'_>, jni::errors::Error> {
jvm.attach_current_thread()View on GitHub (pinned to 6469eb736d)