Skip to content

Commit 93771eb

Browse files
authored
Add configurable JVM memory settings for jdtls (#238)
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.
1 parent e9eab3e commit 93771eb

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

src/config.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ pub fn get_jdtls_launcher(configuration: &Option<Value>, worktree: &Worktree) ->
9494
None
9595
}
9696

97+
/// Returns the max heap size for jdtls (e.g. "2G", "4096m").
98+
/// Maps to the `-Xmx` JVM argument.
99+
pub fn get_max_memory(configuration: &Option<Value>) -> Option<String> {
100+
configuration
101+
.as_ref()
102+
.and_then(|c| c.pointer("/max_memory").and_then(|v| v.as_str()))
103+
.map(|s| s.to_string())
104+
}
105+
106+
/// Returns the initial heap size for jdtls (e.g. "512m", "1G").
107+
/// Maps to the `-Xms` JVM argument. Defaults to "1G".
108+
pub fn get_min_memory(configuration: &Option<Value>) -> Option<String> {
109+
configuration
110+
.as_ref()
111+
.and_then(|c| c.pointer("/min_memory").and_then(|v| v.as_str()))
112+
.map(|s| s.to_string())
113+
}
114+
97115
pub fn get_lombok_jar(configuration: &Option<Value>, worktree: &Worktree) -> Option<String> {
98116
if let Some(configuration) = configuration
99117
&& let Some(jar_path) = configuration

src/jdtls.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ const LOMBOK_REPO: &str = "projectlombok/lombok";
3434
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.";
3535
const JDTLS_VERION_ERROR: &str = "No version to fallback to";
3636

37+
/// Parse a JVM memory string (e.g. "2G", "512m", "1024k") into bytes.
38+
fn parse_memory_value(s: &str) -> Option<u64> {
39+
let s = s.trim();
40+
let (num, multiplier) = match s.as_bytes().last()? {
41+
b'g' | b'G' => (&s[..s.len() - 1], 1024 * 1024 * 1024),
42+
b'm' | b'M' => (&s[..s.len() - 1], 1024 * 1024),
43+
b'k' | b'K' => (&s[..s.len() - 1], 1024),
44+
_ => (s, 1),
45+
};
46+
num.parse::<u64>().ok().map(|n| n * multiplier)
47+
}
48+
3749
pub fn build_jdtls_launch_args(
3850
jdtls_path: &PathBuf,
3951
configuration: &Option<Value>,
@@ -85,13 +97,30 @@ pub fn build_jdtls_launch_args(
8597
"-Dosgi.sharedConfiguration.area.readOnly=true".to_string(),
8698
"-Dosgi.configuration.cascaded=true".to_string(),
8799
"-Djava.import.generatesMetadataFilesAtProjectRoot=false".to_string(),
88-
"-Xms1G".to_string(),
100+
];
101+
{
102+
let mut min =
103+
crate::config::get_min_memory(configuration).unwrap_or_else(|| "1G".to_string());
104+
let mut max = crate::config::get_max_memory(configuration);
105+
if let Some(ref max_val) = max
106+
&& let (Some(min_bytes), Some(max_bytes)) =
107+
(parse_memory_value(&min), parse_memory_value(max_val))
108+
&& min_bytes > max_bytes
109+
{
110+
std::mem::swap(&mut min, max.as_mut().unwrap());
111+
}
112+
args.push(format!("-Xms{min}"));
113+
if let Some(max_val) = max {
114+
args.push(format!("-Xmx{max_val}"));
115+
}
116+
}
117+
args.extend(vec![
89118
"--add-modules=ALL-SYSTEM".to_string(),
90119
"--add-opens".to_string(),
91120
"java.base/java.util=ALL-UNNAMED".to_string(),
92121
"--add-opens".to_string(),
93122
"java.base/java.lang=ALL-UNNAMED".to_string(),
94-
];
123+
]);
95124
args.extend(jvm_args);
96125
args.extend(vec![
97126
"-jar".to_string(),

0 commit comments

Comments
 (0)