System.getProperty(“ java.version”)返回Null

时间:2019-10-11 15:01:15

标签: java processing

我正在尝试编译一个使用Processing 3.4源代码的类。尝试编译扩展StringIndexOutOfBoundsException的类时遇到PApplet问题。

PApplet类包含以下我认为是问题的代码

public class PApplet implements PConstants {
  /** Full name of the Java version (i.e. 1.5.0_11). */
  static public final String javaVersionName =
    System.getProperty("java.version");

  static public final int javaPlatform;
  static {
    String version = javaVersionName;
    if (javaVersionName.startsWith("1.")) {
      version = version.substring(2);
      javaPlatform = parseInt(version.substring(0, version.indexOf('.')));
    } else {
      // Remove -xxx and .yyy from java.version (@see JEP-223)
      javaPlatform = parseInt(version.replaceAll("-.*","").replaceAll("\\..*",""));
    }
  }

我认为字符串javaVersionName设置为null或其他一些奇怪的值,这导致version.indexOf('.')返回-1

堆栈跟踪:

    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:567)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:293)
    at java.lang.Thread.run (Thread.java:830)
Caused by: java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 2
    at java.lang.String.checkBoundsBeginEnd (String.java:3720)
    at java.lang.String.substring (String.java:1909)
    at processing.core.PApplet.<clinit> (PApplet.java:123)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:567)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:293)
    at java.lang.Thread.run (Thread.java:830)

在某处显示at processing.core.PApplet.<clinit> (PApplet.java:123)PApplet.java中的第123行是我上面发布的第一行(public class PApplet ...)。

我怀疑这可能与我的路径和JAVA_HOME系统变量有关。我正在使用JDK 13,它以C:\Program Files\Java\jdk-13\bin的形式添加到我的路径中,并且JAVA_HOME变量设置为C:\Program Files\Java\jdk-13\

编辑:我班上的主要功能是这样的

static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "Demo" };

    if (passedArgs != null) {
        PApplet.main(concat(appletArgs, passedArgs));
    } else {
        PApplet.main(appletArgs);
    }
}

编辑:我还应该提到,我在上面发布的PApplet代码段不是我正在使用的实际资源,只是我在网上找到的内容。我拥有的实际来源在core.jar文件夹中。我无法毫不费力地更改来源。

3 个答案:

答案 0 :(得分:1)

这有两个方面:

  • 在上下文中引发StringIndexOutOfBoundsException的事实意味着javaVersionName字符串不是不是 null,否则,您会得到一个{ {1}}在调用NullPointerException
  • 这里的问题是假设startsWith之后的字符串部分将有另一个点

有各种Java主要版本和供应商,并且版本会随之变化。

您应该只调试代码并推断那里返回的值是什么。

作为一个可能不相关的注释,如果您的应用程序是一个applet,则您也要保持谨慎:

  

安全考虑:可以限制对系统属性的访问   由安全经理。在applet中,这通常是一个问题,   被阻止读取某些系统属性和写入   任何系统属性。有关在中访问系统属性的更多信息   小程序,请参阅《使用Java进行更多操作》中的“系统属性”。   互联网应用课程。

来源here

答案 1 :(得分:0)

您似乎在作弊;)

9发行版以来,您所显示的代码已经在正确处理Java版本的修补程序之后-在这里,您的主要发行版和修补版本的版本略有不同。

您的core.jar似乎已预先提交:

https://github.com/processing/processing/commit/b0b2d89228c8bf178f5113a4af25779a14f242e1#diff-29e1de29464981394819a89e38e87288

修复了java.version属性的处理。

因此,您的示例代码应阅读

public class PApplet {
  static public final String javaVersionName =
    System.getProperty("java.version");

  static public final int javaPlatform =
     PApplet.parseInt(PApplet.split(javaVersionName, '.')[1]);


  static public String[] split(String value, char delim) {
    // do this so that the exception occurs inside the user's
    // program, rather than appearing to be a bug inside split()
    if (value == null) return null;
    //return split(what, String.valueOf(delim));  // huh

    char chars[] = value.toCharArray();
    int splitCount = 0; //1;
    for (int i = 0; i < chars.length; i++) {
      if (chars[i] == delim) splitCount++;
    }
    // make sure that there is something in the input string
    //if (chars.length > 0) {
      // if the last char is a delimeter, get rid of it..
      //if (chars[chars.length-1] == delim) splitCount--;
      // on second thought, i don't agree with this, will disable
    //}
    if (splitCount == 0) {
      String splits[] = new String[1];
      splits[0] = value;
      return splits;
    }
    //int pieceCount = splitCount + 1;
    String splits[] = new String[splitCount + 1];
    int splitIndex = 0;
    int startIndex = 0;
    for (int i = 0; i < chars.length; i++) {
      if (chars[i] == delim) {
        splits[splitIndex++] =
          new String(chars, startIndex, i-startIndex);
        startIndex = i + 1;
      }
    }
    //if (startIndex != chars.length) {
      splits[splitIndex] =
        new String(chars, startIndex, chars.length-startIndex);
    //}
    return splits;
  }

  static final public int parseInt(String what) {
    return parseInt(what, 0);
  }

  static final public int parseInt(String what, int otherwise) {
    try {
      int offset = what.indexOf('.');
      if (offset == -1) {
        return Integer.parseInt(what);
      } else {
        return Integer.parseInt(what.substring(0, offset));
      }
    } catch (NumberFormatException e) { }
    return otherwise;
  }

  public static void main(String [] args) {
    System.out.println("Java version: " + javaPlatform);
  }
}

和主要

public class Main {
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "Demo" };

    PApplet.main(appletArgs);
  }
}

您将获得例外的地方

> javac PApplet.java
> javac Main.java
> java -cp . Main
Exception in thread "main" java.lang.ExceptionInInitializerError
    at Main.main(Main.java:7)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
    at PApplet.<clinit>(PApplet.java:6)
    ... 1 more

如果使用注释中建议的勾号,则可以将其“修复”

public class Main {
  static public void main(String[] passedArgs) {
    String[] appletArgs = new String[] { "Demo" };

    System.setProperty("java.version", "1.1.1");

    PApplet.main(appletArgs);
  }
}

您将使代码运行

> javac PApplet.java
> javac Main.java
> java -cp . Main
Java version: 1

因此,最后,为什么不从最新资源构建它? :)

替代方法-有点hacky

比方说,您既不能更改Main.java也不能更改core.jar。您在这里可以做的是欺骗Java,在哪里寻找PApplet.class。您可以创建一个目录-称其为fix。在fix内部,您只能编译一个类:PApplet.java。然后,您可以运行如下代码:

> java -cp fix:. Main

其中的修复程序包含您特制的版本

public class PApplet {
  static public final String javaVersionName =
    System.getProperty("java.version");

  static public final int javaPlatform = 1;

  public static void main(String [] args) {
    System.out.println("Java version: " + javaPlatform);
  }
}

答案 2 :(得分:-1)

问题在这里:

 //supposing Java version 18.9
 version = version.substring(2);
 //now version is equal to "9"
 javaPlatform = parseInt(version.substring(0, version.indexOf('.')));//error! because indexOf('.') return -1 since '.' is not found in variable version

因此,indexOf('.')返回-1,而subString(0,-1)引发StringIndexOutOfBoundsException