bugGNU Octave - Bugs: bug #60058, version("-java")...

 
 

bug #60058: version("-java") possibly returns wrong info

Submitted by:  Ernst Reissner <ernstreissner>
Submitted on:  Sun 14 Feb 2021 09:24:09 PM UTC  
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  None
Status:  Need Info Assigned to:  None
Originator Name:  Reissner Open/Closed:  Open
Release:  dev Operating System:  Any

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

( Jump to the original submission)

Mon 01 Mar 2021 08:20:31 AM UTC, comment #19: 

Re-titling the report and re-opening for the possible issue pointed out in comment #13.

To get back on track, I'll repeat the questions from comment #16:
I'm not an expert at all in Java development. But if I understand the code snippet correctly, it overrides any properties a user might have set manually in that namespace(?).
Should overridden properties be reset after that?

I'll add another one: Could it be that a Java developer (using Octave) explicitly overrides these version related properties to get the respective results (maybe to "fool" their code to run with different code paths for testing)? Should we be overriding what that developer set?

Markus Mützel <mmuetzel>
Project Member
Mon 01 Mar 2021 12:12:46 AM UTC, comment #18: 

@philip:
you discuss many different issues in one post.
First, yes I hate it also that matlab convolutes all into one version string.
version('-java') as defined by matlab,
is by no means just the version, but comprises also vendor information.
Ugly. But no choice, octave is a clone and cannot do better.

On the other hand, maybe, it is acceptable to add another parameter, so like

v=version('-java','struct')

delivering all needed information
in a struct so that the user can fetch what (s)he wants.
E.g. v.java_version.

A problem is also.. what is version??
If i have a look at my result, i have the impression,
what is returned by octave and also by matlab
is the property java.runtime.version.

Please have a look at
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/System.html#getProperties()
There are also older docs for older java releases.
But java.runtime.version is not among the mandatory properites.
This means, a jvm is not required to implement it.

What is supported as mandatory is e.g. java.version
and starting with java 11 this is the same as Runtime.version()
which is very strictly specified.
It comprises at least of 3 numbers (trailing 0 not displayed)
separated by '.'. This is going to remain stable.
Of course, java.runtime.version is not stable.

There are further kinds of mandatory versions as you can see from the property list and there are more which are not mandatory.
I think the runtime version is good for bugfixing
because then you know more where it comes from.
For me as a package provider, java.version or Runtime.version()
(defined since java 9) would be fine.
Advantage: this is clearly specified and it is the same as the property java.version.
I would like to see it as part of return of

version('-java','struct')

i suggested above.

Finally let me point out that java.version is a property
which can be changed.
System.setProperties(null) triggers re-initialization.
But i think clearer is to use Runtime.version().

Ernst Reissner <ernstreissner>
Sun 28 Feb 2021 09:58:02 PM UTC, comment #17: 

Matlab's "version" returns the version of the bundled Java JRE; in Octave one must select an external one from perhaps several Java releases installed side-by-side, easily done by setting JAVA_HOME. So it works differently to start with.

That said, I wonder why in version.m all those Java properties are requested and wrapped into a convoluted string that needs quite some back-untangling before it can be used for automating Java version analysis.

In the io package there's private function __chk_java_sprt__.m that invokes a different Java method, that until now AFAICS has worked with all Java releases and -vendors on at least Windows and Linux:

  :
    jver = ...
      char (javaMethod ("getProperty", "java.lang.System", "java.version"));
    cjver = strsplit (jver, ".");
    ## Before Java 9 the numbering scheme is "1.ver.x_y".
    ## For Java 9 it is "ver.x.y".
    ## For Java 10 and 11 it is just "ver".
    java_ver = [];
    if (numel (cjver) > 1 && (sscanf (cjver{1}, "%d") == 1))
      java_ver = sscanf (cjver{2}, "%d");
    elseif (! isempty (cjver))
      java_ver = sscanf (cjver{1}, "%d");
    endif
  :

(I just saw that it works with Java 15 as well BTW).
I suppose this code could be morphed into s/th returning an 'x.y.z' version number and then be included in javamem.m to return a second output arg returning that version number.
javamem.m has no Matlab counterpart so it's easy to amend.

Philip Nienhuis <philipnienhuis>
Project Member
Tue 16 Feb 2021 01:12:03 PM UTC, comment #16: 

I'm not an expert at all in Java development. But if I understand the code snippet correctly, it overrides any properties a user might have set manually in that namespace(?).
Should overridden properties be reset after that?

Could you please provide a patch that can be applied on top of a current tip of the default branch (preferably complete with a commit message).

Please, keep the changes to the documentation and to the behavior separate. (The documentation changes can probably be applied to the stable branch.)

Markus Mützel <mmuetzel>
Project Member
Tue 16 Feb 2021 09:58:44 AM UTC, comment #15: 

patch:

try
   javaMethod('setProperties', 'java.lang.System',[]),        
   jversion = javaMethod ("getProperty", "java.lang.System", ...
                                 "java.runtime.version");

I think, the form
"Java " jversion " with " jvendor " " jname " " jjitmode
e.g. starting with "Java " is the responsibility of octave.
Also "no usable...".
What the jversion is, is java specification.
Why not documenting:
Returns a version string of the form
"Java <jversion> with <jvendor> <jvmname> <jvminfo>
where the java version,  vendor, JVM name and jvminfo
are given by the according java system properties.

Ernst Reissner <ernstreissner>
Tue 16 Feb 2021 09:38:19 AM UTC, comment #14: 

Ernst, it is out of reach of Octave, what a Java vendor might decide to return for each of these components. Will `jversion` always start with some combination of dots and digits? I don't know.
You are free to decide what you would like to parse and how.

I'll be happy to review a patch if you think that something is wrong with this function.

Markus Mützel <mmuetzel>
Project Member
Tue 16 Feb 2021 09:30:53 AM UTC, comment #13: 

Ah i see, but then your comment
'It is not in the scope of the Octave project to document which version strings different vendors of different components return. (Those projects could also decide to change the format.)'

is clueless,
["Java " jversion " with " jvendor " " jname " " jjitmode]
specifies the shape of the return value.
So it is clear that a regular expression is to process it
and which one.
Well as long as java is installed at all.

By the way, it is not safe to implement like that.
System.setProperty("java.version", "b;a");
//System.setProperties(null);
System.out.println(System.getProperty("java.version"));
yields b;a,
only when uncommenting the middle line, the correct version occurs.
so needed is javaMethod('setProperties', 'java.lang.System',[]),
[] signifying null.

Ernst Reissner <ernstreissner>
Tue 16 Feb 2021 09:10:03 AM UTC, comment #12: 

Octave is open source. If you wonder where return values come from, you can have a look at the code.

See this part of "version.m":

     case "-java"
        try
          jversion = javaMethod ("getProperty", "java.lang.System", ...
                                 "java.runtime.version");
          jvendor = javaMethod ("getProperty", "java.lang.System", ...
                                "java.vendor");
          jname = javaMethod ("getProperty", "java.lang.System", ...
                              "java.vm.name");
          jjitmode = javaMethod ("getProperty", "java.lang.System", ...
                                 "java.vm.info");
          v = ["Java " jversion " with " jvendor " " jname " " jjitmode];
        catch err
          v = sprintf ("no usable Java Runtime Environment (%s) found:\n%s", ...
                       uname ().machine, err.message);
        end_try_catch

Markus Mützel <mmuetzel>
Project Member
Tue 16 Feb 2021 08:32:34 AM UTC, comment #11: 

I agree as long as they just pass.
But I wonder whether octave assembles the version string itself.

look:
java --version yields
openjdk 11.0.10 2021-01-19
OpenJDK Runtime Environment (build 11.0.10+9-suse-1.1-x8664)
OpenJDK 64-Bit Server VM (build 11.0.10+9-suse-1.1-x8664, mixed mode)

whereas
octave:1> version('-java')
ans = Java 11.0.10+9-suse-1.1-x8664 with Oracle Corporation OpenJDK 64-Bit Server VM mixed mode

So, octave does something.
Else, maybe: 'version('-java') returns version as returned by...
I dont know.
Note that also vendor information is returned.

Anyway, i removed my own version method, although more precise,
to use the generic one with the regular expression
you suggested.

Ernst Reissner <ernstreissner>
Tue 16 Feb 2021 08:25:24 AM UTC, comment #10: 

It is not in the scope of the Octave project to document which version strings different vendors of different components return. (Those projects could also decide to change the format.)

Markus Mützel <mmuetzel>
Project Member
Tue 16 Feb 2021 08:19:44 AM UTC, comment #9: 

Ah ok, I understood.
You are right, it shall be clarified,
what precisely the output of  version('-java') is.
Maybe docs shall give a hint that it is more than the version.
It would be helpful in deciding whether regular expressions
are the right means to treat.

Also it shall be documented what happens
if java is not installed at all.

I had a look at all the other features,
the output really strongly depends on the feature.

Ernst Reissner <ernstreissner>
Tue 16 Feb 2021 07:07:01 AM UTC, comment #8: 

I didn't write that you can't use a regular expression. I only wrote that the regular expression in comment #5 might not be generic enough. There are a few questions that you should ask yourself when implementing such a function, e.g.: Do the version strings for all JRE vendors look similar enough? Do the version numbers for all JRE vendors consist of only dots and numbers? What if no JRE is installed at all?

Anyway: Imho, the function you propose is probably best to be implemented in user code (not in core Octave).

Closing report.

Markus Mützel <mmuetzel>
Project Member
Mon 15 Feb 2021 06:55:39 PM UTC, comment #7: 

I dont know, for me, docs is not clear, maybe i dont understand.
version is not generic. But with reg exps one can make it generic.
So whats the problem.

Ernst Reissner <ernstreissner>
Mon 15 Feb 2021 05:55:32 PM UTC, comment #6: 

Just to be clear: The regular expression in comment #5 is probably not what you should use in a generic function. It was just to demonstrate that `compare_version` does work if used correctly.

Markus Mützel <mmuetzel>
Project Member
Mon 15 Feb 2021 05:45:02 PM UTC, comment #5: 

Well, you'd need to read the documentation for `compare_version` first.
If I use it according to its specification it works fine for me:

>> version -java
ans = Java 11.0.9.1+1-Ubuntu-0ubuntu1.20.10 with Ubuntu OpenJDK 64-Bit Server VM mixed mode, sharing
>> java_ver = regexp(version("-java"), 'Java ([0-9\.]*)', "tokens");
>> compare_versions (java_ver{1}{1}, "11.0.9.1", "<=")
ans = 1
>> compare_versions (java_ver{1}{1}, "11.0.9.01", "<=")
ans = 1

Markus Mützel <mmuetzel>
Project Member
Mon 15 Feb 2021 05:15:03 PM UTC, comment #4: 

Great idea. Look at it:
octave:17> version('-java')
ans = Java 11.0.10+9-suse-1.1-x8664 with Oracle Corporation OpenJDK 64-Bit Server VM mixed mode
octave:18> compare_versions ('Java 11.0.5', version('-java'),'<=')
ans = 0
octave:19> compare_versions ('Java 11.0.05', version('-java'),'<=')
ans = 1

This is buggy as hell.
I think if there is no spec whats the form of the version.. well...
no trust.

I would like to suggest an improvement over compare_versions:
two arguments only
Result is -1, 0,1 if < == >.
With that you can implement the operators yourself in an obvious and elegant way.

Ernst Reissner <ernstreissner>
Mon 15 Feb 2021 04:45:48 PM UTC, comment #3: 

Currently, you could query which JRE would be picked up by Octave with `version -java`.
Additionally, there is the function `compare_versions`.

Does a combination of those work for you?

Markus Mützel <mmuetzel>
Project Member
Mon 15 Feb 2021 02:20:07 PM UTC, comment #2: 

See also my comment #3 in bug #60054

Philip Nienhuis <philipnienhuis>
Project Member
Mon 15 Feb 2021 01:16:02 PM UTC, comment #1: 

maybe we need two things:
the version shall allow a string representation
but also a comparison.

Ernst Reissner <ernstreissner>
Sun 14 Feb 2021 09:24:09 PM UTC, original submission:  

I think one needs a function displaying the version
of the java virtual machine JVM.

This is very simple to do:

%% -*- texinfo -*-
%% @deftypefn  {Function File} {@var{res}} javaversion()
%%
%% Returns the java version as a string
%% of the form @code{major.minor.update-patch}.
%%
%%  @example
%%    javaversion()
%%  @end example
%%
%% @end deftypefn

function str = javaversion()
  v = javaMethod("version", "java.lang.Runtime");
  str = [num2str(v.feature()) "." num2str(v.interim()) "." num2str(v.update()) "-" num2str(v.patch())];
endfunction

This allows also to check versions:

v = javaMethod("version", "java.lang.Runtime");
v11 = javaMethod("parse", "java.lang.Runtime$Version", "11.3.2.3");
v16 = javaMethod("parse", "java.lang.Runtime$Version", "16.1.0.1");
printf("versions this to max %d, this to min %d" ,v.compareTo(v16),v.compareTo(v11))

a.compareTo(b) >=0 iff a >= b and so on.
This allows to check java versions
in the context of package loading.

Ernst Reissner <ernstreissner>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by ernstreissner (Submitted the item)
  • -email is unavailable- added by ernstreissner
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only project members can vote.

     

     

     

    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2021-03-01 mmuetzel StatusWont Fix => Need Info
        Open/ClosedClosed => Open
        SummaryFeature request: function javaversion() => version("-java") possibly returns wrong info
    2021-02-16 mmuetzel StatusNone => Wont Fix
        Open/ClosedOpen => Closed
    2021-02-14 ernstreissner Carbon-Copy- => Added rei3ner@arcor.de

    Back to the top


    Powered by Savane 3.6