System.getProperty ("java.version") возвращает значение Null - PullRequest
0 голосов
/ 11 октября 2019

Я пытаюсь скомпилировать класс, который использует исходный код 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). Строка 123 в PApplet.java - это первая строка (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 ]

1 голос
/ 11 октября 2019

Это имеет два аспекта:

  • сам факт, что StringIndexOutOfBoundsException выбрасывается в контексте, подразумевает, что строка javaVersionName равна , а не nullв противном случае вы получите NullPointerException при вызове startsWith
  • Проблема заключается в том, что часть строки после 1. будет иметь другую точку

Существуют различные основные версии и поставщики Java, и версии меняются в зависимости от этого.

Вы должны просто отладить свой код и сделать вывод, что именно является возвращаемым значением.

В качестве, вероятно, не связанной заметки, вы также должны быть осторожны, если (как следует из названия класса) ваше приложение является апплетом:

Замечание по безопасности: доступ к системным свойствам можетбыть ограниченным менеджером безопасности. Это чаще всего проблема в апплетах, которые не могут читать некоторые системные свойства и записывать какие-либо системные свойства. Дополнительные сведения о доступе к системным свойствам в апплетах см. В разделе «Системные свойства» в уроке «Больше с помощью богатых интернет-приложений Java».

Источник здесь .

0 голосов
/ 11 октября 2019

Похоже, вы немного обманываете;)

Код, который вы показали, уже после исправления для правильной обработки версии Java с момента выпуска 9 - здесь у вас немного другая версиядля основных версий и исправленных версий.

Похоже, что ваш 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

Итак, в заключение, почему бы не собрать его из большинствапоследние источники? :)

Альтернативный подход - немного хакерский

Допустим, вы не можете изменить ни 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);
  }
}
0 голосов
/ 11 октября 2019

Проблема здесь:

 //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

...