From 62030e9b490d6d38512b42251858c95845f75150 Mon Sep 17 00:00:00 2001 From: Riccardo Strina Date: Tue, 5 May 2026 18:35:59 +0200 Subject: [PATCH 1/3] Add configurable JVM memory settings for jdtls Add `get_max_memory` and `get_min_memory` config functions to read heap size settings. Implement `parse_memory_value` to convert JVM memory strings (e.g. "2G", "512m") to bytes. Update launch args to use configured values with validation to ensure min doesn't exceed max, defaulting to "1G" for initial heap. --- src/config.rs | 18 ++++++++++++++++++ src/jdtls.rs | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/config.rs b/src/config.rs index 9aa99e7..30cdbb3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -94,6 +94,24 @@ pub fn get_jdtls_launcher(configuration: &Option, worktree: &Worktree) -> None } +/// Returns the max heap size for jdtls (e.g. "2G", "4096m"). +/// Maps to the `-Xmx` JVM argument. +pub fn get_max_memory(configuration: &Option) -> Option { + configuration + .as_ref() + .and_then(|c| c.pointer("/max_memory").and_then(|v| v.as_str())) + .map(|s| s.to_string()) +} + +/// Returns the initial heap size for jdtls (e.g. "512m", "1G"). +/// Maps to the `-Xms` JVM argument. Defaults to "1G". +pub fn get_min_memory(configuration: &Option) -> Option { + configuration + .as_ref() + .and_then(|c| c.pointer("/min_memory").and_then(|v| v.as_str())) + .map(|s| s.to_string()) +} + pub fn get_lombok_jar(configuration: &Option, worktree: &Worktree) -> Option { if let Some(configuration) = configuration && let Some(jar_path) = configuration diff --git a/src/jdtls.rs b/src/jdtls.rs index 18972a1..ffaeb83 100644 --- a/src/jdtls.rs +++ b/src/jdtls.rs @@ -34,6 +34,18 @@ const LOMBOK_REPO: &str = "projectlombok/lombok"; const JAVA_VERSION_ERROR: &str = "JDTLS requires at least Java version 21 to run. You can either specify a different JDK to use by configuring lsp.jdtls.settings.java_home to point to a different JDK, or set lsp.jdtls.settings.jdk_auto_download to true to let the extension automatically download one for you."; const JDTLS_VERION_ERROR: &str = "No version to fallback to"; +/// Parse a JVM memory string (e.g. "2G", "512m", "1024k") into bytes. +fn parse_memory_value(s: &str) -> Option { + let s = s.trim(); + let (num, multiplier) = match s.as_bytes().last()? { + b'g' | b'G' => (&s[..s.len() - 1], 1024 * 1024 * 1024), + b'm' | b'M' => (&s[..s.len() - 1], 1024 * 1024), + b'k' | b'K' => (&s[..s.len() - 1], 1024), + _ => (s, 1), + }; + num.parse::().ok().map(|n| n * multiplier) +} + pub fn build_jdtls_launch_args( jdtls_path: &PathBuf, configuration: &Option, @@ -85,13 +97,29 @@ pub fn build_jdtls_launch_args( "-Dosgi.sharedConfiguration.area.readOnly=true".to_string(), "-Dosgi.configuration.cascaded=true".to_string(), "-Djava.import.generatesMetadataFilesAtProjectRoot=false".to_string(), - "-Xms1G".to_string(), + ]; + { + let mut min = crate::config::get_min_memory(configuration).unwrap_or_else(|| "1G".to_string()); + let mut max = crate::config::get_max_memory(configuration); + if let Some(ref max_val) = max { + if let (Some(min_bytes), Some(max_bytes)) = (parse_memory_value(&min), parse_memory_value(max_val)) { + if min_bytes > max_bytes { + std::mem::swap(&mut min, max.as_mut().unwrap()); + } + } + } + args.push(format!("-Xms{min}")); + if let Some(max_val) = max { + args.push(format!("-Xmx{max_val}")); + } + } + args.extend(vec![ "--add-modules=ALL-SYSTEM".to_string(), "--add-opens".to_string(), "java.base/java.util=ALL-UNNAMED".to_string(), "--add-opens".to_string(), "java.base/java.lang=ALL-UNNAMED".to_string(), - ]; + ]); args.extend(jvm_args); args.extend(vec![ "-jar".to_string(), From 988995a843c4d29e8cfd51f06f2816d5427a2044 Mon Sep 17 00:00:00 2001 From: Riccardo Strina Date: Tue, 5 May 2026 18:45:33 +0200 Subject: [PATCH 2/3] Apply fmt and clippy --- src/jdtls.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jdtls.rs b/src/jdtls.rs index ffaeb83..226cc63 100644 --- a/src/jdtls.rs +++ b/src/jdtls.rs @@ -99,15 +99,15 @@ pub fn build_jdtls_launch_args( "-Djava.import.generatesMetadataFilesAtProjectRoot=false".to_string(), ]; { - let mut min = crate::config::get_min_memory(configuration).unwrap_or_else(|| "1G".to_string()); + let mut min = + crate::config::get_min_memory(configuration).unwrap_or_else(|| "1G".to_string()); let mut max = crate::config::get_max_memory(configuration); - if let Some(ref max_val) = max { - if let (Some(min_bytes), Some(max_bytes)) = (parse_memory_value(&min), parse_memory_value(max_val)) { - if min_bytes > max_bytes { + if let Some(ref max_val) = max + && let (Some(min_bytes), Some(max_bytes)) = + (parse_memory_value(&min), parse_memory_value(max_val)) + && min_bytes > max_bytes { std::mem::swap(&mut min, max.as_mut().unwrap()); } - } - } args.push(format!("-Xms{min}")); if let Some(max_val) = max { args.push(format!("-Xmx{max_val}")); From 434c24edfbc07818c06ed58cbd3234078d6eec54 Mon Sep 17 00:00:00 2001 From: Riccardo Strina Date: Tue, 5 May 2026 18:48:05 +0200 Subject: [PATCH 3/3] fmt and clippy on missed file --- src/jdtls.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/jdtls.rs b/src/jdtls.rs index 226cc63..5bcb23a 100644 --- a/src/jdtls.rs +++ b/src/jdtls.rs @@ -105,9 +105,10 @@ pub fn build_jdtls_launch_args( if let Some(ref max_val) = max && let (Some(min_bytes), Some(max_bytes)) = (parse_memory_value(&min), parse_memory_value(max_val)) - && min_bytes > max_bytes { - std::mem::swap(&mut min, max.as_mut().unwrap()); - } + && min_bytes > max_bytes + { + std::mem::swap(&mut min, max.as_mut().unwrap()); + } args.push(format!("-Xms{min}")); if let Some(max_val) = max { args.push(format!("-Xmx{max_val}"));