Skip to content

Instantly share code, notes, and snippets.

@scivision
Created August 13, 2025 14:21
Show Gist options
  • Save scivision/fb80ef7d3fb959a515e52b1698aa3f56 to your computer and use it in GitHub Desktop.
Save scivision/fb80ef7d3fb959a515e52b1698aa3f56 to your computer and use it in GitHub Desktop.
GNU Octave Java JDK notes

Configure GNU Octave JVM

GNU Octave JVM can be configured with the JAVA_HOME environment variable. Some install packages don't include Java.

For example, with Homebrew:

brew install octave openjdk

On Windows install JDK as like Matlab above.

setenv("JAVA_HOME", "/path/to/openjdk/")

This setenv() is not persistent. If it works, add the working setenv() command to .octaverc

GNU Octave Java API.

Use Matlab JRE in GNU Octave

If Matlab is installed, GNU Octave can use the same JRE as Matlab. Do so like:

je = jenv();
% Tell the JAVA_HOME directory
disp(je.Home)

Then set the JAVA_HOME environment variable to the JRE directory in Octave:

setenv("JAVA_HOME", "value from je.Home")

Be sure on Windows to use file separator "/" as "" will not work. Within Octave:

setenv("JAVA_HOME", "C:/Program Files/MATLAB/R2025a/sys/java/jre/win64/jre")

version("-java")

ans = Java 1.8.0_202-b08 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode

Troubleshooting

If OpenJDK version updates, GNU Octave might not automatically find the new version:

libjvm: failed to load

To correct this, find the path to the new JVM.. For example, on macOS:

gfind $(brew --prefix) -name libjvm.dylib

Within Octave, tell Octave the directory that libjvm is under by setenv("JAVA_HOME", "<path to libjvm directory>").

%% SUBPROCESS_RUN run external program for GNU Octave only
%
% with optional cwd, env. vars, stdin, timeout
%
% handles command lines with spaces
% input each segment of the command as an element in a string array
% this is how python subprocess.run works
%
%%% Inputs
% * cmd_array: cell of char to compose a command line
% * env: environment variable struct to set
% * cwd: working directory to use while running command
% * stdin: string to pass to subprocess stdin pipe
% * timeout: time to wait for process to complete before erroring (seconds)
%%% Outputs
% * status: 0 is generally success. -1 if timeout. Other codes as per the
% program / command run
% * stdout: stdout from process
% * stderr: stderr from process
%
%% Example
% subprocess_run({'mpiexec', '-help2'})
%
% NOTE: if cwd option used, any paths must be absolute or relative to cwd.
% otherwise, they are relative to pwd.
%
% uses Java ProcessBuilder interface to run subprocess and use stdin/stdout pipes
% https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ProcessBuilder.html
function [status, stdout, stderr] = subprocess_run(cmd, env, cwd, stdin, timeout)
if ischar(cmd), cmd = {cmd}; end
if nargin < 2 || isempty(env), env = struct(); end
if nargin < 3, cwd = ''; end
if nargin < 4, stdin = ''; end
if nargin < 5, timeout = 0; end
%% process instantiation
% https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/ProcessBuilder.html#command(java.lang.String...)
jcary = javaArray("java.lang.String", length(cmd));
for i = 1:length(cmd)
jcary(i) = javaObject("java.lang.String", cmd{i});
end
proc = javaObject("java.lang.ProcessBuilder", jcary);
if ~isempty(fieldnames(env))
% https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/ProcessBuilder.html#environment()
jenv = proc.environment();
fields = fieldnames(env);
for i = 1:length(fields)
jenv.put(fields{i}, env.(fields{i}));
% jenv.put(fields{i}, javaObject("java.lang.String", env.(fields{i})));
end
end
if ~stdlib.strempty(cwd)
% https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/ProcessBuilder.html#directory(java.io.File)
proc.directory(javaObject("java.io.File", cwd));
end
%% start process
% https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/ProcessBuilder.html#start()
h = proc.start();
%% stdin pipe
if ~stdlib.strempty(stdin)
os = javaObject("java.io.OutputStream", h.getOutputStream());
writer = javaObject("java.io.BufferedWriter", os);
writer.write(stdin);
writer.flush()
writer.close()
end
%% read stdout, stderr pipes
stdout = read_stream(h.getInputStream());
stderr = read_stream(h.getErrorStream());
%% wait for process to complete
% https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/Process.html#waitFor()
tmsg = '';
if timeout > 0
% returns true if process completed successfully
% returns false if process did not complete within timeout
sec = javaMethod("valueOf", "java.util.concurrent.TimeUnit", "SECONDS");
b = h.waitFor(timeout, sec);
if b
status = 0;
else
tmsg = 'Subprocess timeout';
status = -1;
end
else
% returns 0 if process completed successfully
status = h.waitFor();
end
%% close process
h.destroy();
stderr = strcat(tmsg, stderr);
if nargout < 2 && ~stdlib.strempty(stdout)
disp(stdout)
end
if nargout < 3 && ~stdlib.strempty(stderr)
warning(stderr)
end
end
function msg = read_stream(stream)
% https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/io/BufferedReader.html
reader = javaObject("java.io.BufferedReader", javaObject("java.io.InputStreamReader", stream));
line = reader.readLine();
msg = '';
while ~isempty(line)
msg = strcat(msg, line, newline);
line = reader.readLine();
end
msg = strtrim(msg);
reader.close();
stream.close();
end
%!test
%! if ispc, c = "dir"; else, c = "ls"; end
%! [r, m, e] = subprocess_run(c);
%! assert(r == 0)
%! assert(length(m) > 0)
%! assert(length(e) == 0)
%! [r, mc, e] = subprocess_run(c, [], '/');
%! assert(r == 0)
%! assert(!strcmp(m, mc))
%!testif 0
%! names = {'TEST1', 'TEST2'};
%! vals = {'test123', 'test321'};
%! env = struct(names{1}, vals{1}, names{2}, vals{2});
%! for i = 1:length(names)
%! if ispc
%! c = {"cmd", "/c", "echo", strcat('%', names{i}, '%')};
%! else
%! c = {"echo", strcat('$', names{i})};
%! end
%! [r, m, e] = subprocess_run(c, env);
%! assert(r == 0)
%! assert(strcmp(m, vals{i}), '%s != %s', m, vals{i})
%! assert(length(e) == 0)
%! end
%!test
%! c = "../test/sleep.exe";
%! if isfile(c)
%! [r, m, e] = subprocess_run(c, [], [], [], 1);
%! assert(r == -1)
%! assert(length(m) == 0)
%! assert(strncmp(e, 'Subprocess timeout', 17))
%! end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment