Почему не может, System.setProperty () изменяют путь к классу во времени выполнения?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

16
задан Community 23 May 2017 в 12:26
поделиться

4 ответа

Можно, конечно, установить любые системные свойства, которые Вы хотите в любом моменте времени. Вопрос, он будет иметь какой-либо эффект? В случае пути к классу ответ НЕТ. Системный загрузчик класса инициализируется в очень ранней точке в последовательности запуска. Это копирует путь к классу в свои собственные структуры данных, и свойство пути к классу не читается снова. Изменение его ни на что не влияет в системе.

причина этого может быть двукратной. Меньшей причиной является производительность. Вы, возможно, должны создать своего рода структуру данных для быстрого поиска ресурсов, и повторно анализирующий путь к классу, каждый раз может быть неэффективным. Более важной причиной является безопасность. Вы не хотите изменения класса жулика путь к классу под Вами и загружаете поставившую под угрозу версию другого класса.

13
ответ дан 30 November 2019 в 16:30
поделиться

System.setProperty может использоваться для установки некоторого менеджера безопасности или обработчика протокола в начале программы. Как:

/*
Add the URL handler to the handler property. This informs 
IBMJSSE what URL handler to use to handle the safkeyring 
support. In this case IBMJCE.
*/
System.setProperty("java.protocol.handler.pkgs", "com.ibm.crypto.provider");

или для SSL использования:

System.setProperty("javax.net.ssl.keyStore", context.getRealPath(KEYSTORE));
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.trustStore", context.getRealPath(TRUSTSTORE));
System.setProperty("javax.net.debug", "ssl");
HttpClient httpClient = new HttpClient();
GetMethod httpGet = new GetMethod("https://something.com");
httpClient.executeMethod(httpGet);
return new String(httpGet.getResponseBody());

, Но остерегаются, потому что это изменения среда во времени выполнения для ВЕСЬ приложения, работающие в том же jvm.
, Если, например, одно приложение должно работать с саксом и другим с xalan и оба используют System.setProperty для установки transformerFactory, то Вы столкнетесь с проблемой

, Как сказано в статья Monitored System.setProperty ,
, System.setProperty () может быть злым вызовом.

  • Это - 100%, враждебных к потоку
  • , Это содержит суперглобальные переменные
  • , чрезвычайно трудно отладить, когда эти переменные загадочно изменяются во времени выполнения
<час>

Относительно свойства пути к классу, как я сказал в предыдущем вопросе , это не может быть легко изменено как время выполнения.

, В частности, свойство System Java java.class.path используется для создания связанной ссылки, когда JRE инстанцируют, тогда не перечитан . Поэтому изменения, которые Вы вносите в свойство, ничего действительно не делают к существующей виртуальной машине.

10
ответ дан 30 November 2019 в 16:30
поделиться

Основная идея о getProperty() состоит в том, что программы/код могут быть настроены от за пределами JVM, передающих свойств на командной строке с помощью java -Dfoo=bar синтаксис.

, Поскольку можно хотеть настроить определенное поведение в других компонентах программного обеспечения (таких как регистрирующийся компонент) в ситуациях, где Вы не управляете командной строкой - думают, будучи развернутым в контейнере Сервлета - setProperty(), входит как удобный способ программно изменить настройки, например, прежде, чем инстанцировать Вашей утилиты входа.

проблема, которая показана эти classpath проблема, состоит в том, что программы обычно только считают такие системные свойства точно однажды, когда они будут сначала инициализированы. Так изменяя путь к классу после того, как запуск JVM ничего не изменяет для Вас само приложение, потому что JVM уже инициализируется, и изменяющий некоторую регистрирующуюся конфигурацию после того, как Вы уже получили экземпляр Регистратора (или безотносительно), обычно не будет иметь никакого эффекта также.

0
ответ дан 30 November 2019 в 16:30
поделиться

Изменить путь к классам

Несмотря на то, что вы не можете установить путь к классам, используя системные свойства (поскольку JVM считывает системные свойства один раз: при запуске), вы все равно можете изменить путь к классам, принудительно вызвав addURL метод загрузчика классов. Обратите внимание, что в приведенном ниже решении не учитывается текущий поток. Следовательно, это может быть не во всех ситуациях.

Пример решения

Исходный источник следующего кода на веб-сайте Sun был удален:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;                   

import java.io.File;
import java.io.IOException;

import java.net.URL;
import java.net.URLClassLoader;

/**
 * Allows programs to modify the classpath during runtime.              
 */                                                                     
public class ClassPathUpdater {                                         
  /** Used to find the method signature. */                             
  private static final Class[] PARAMETERS = new Class[]{ URL.class };   

  /** Class containing the private addURL method. */
  private static final Class<?> CLASS_LOADER = URLClassLoader.class;

  /**
   * Adds a new path to the classloader. If the given string points to a file,
   * then that file's parent file (i.e., directory) is used as the
   * directory to add to the classpath. If the given string represents a
   * directory, then the directory is directly added to the classpath.
   *
   * @param s The directory to add to the classpath (or a file, which
   * will relegate to its directory).
   */
  public static void add( String s )
    throws IOException, NoSuchMethodException, IllegalAccessException,
           InvocationTargetException {
    add( new File( s ) );
  }

  /**
   * Adds a new path to the classloader. If the given file object is
   * a file, then its parent file (i.e., directory) is used as the directory
   * to add to the classpath. If the given string represents a directory,
   * then the directory it represents is added.
   *
   * @param f The directory (or enclosing directory if a file) to add to the
   * classpath.
   */
  public static void add( File f )
    throws IOException, NoSuchMethodException, IllegalAccessException,
           InvocationTargetException {
    f = f.isDirectory() ? f : f.getParentFile();
    add( f.toURI().toURL() );
  }

  /**
   * Adds a new path to the classloader. The class must point to a directory,
   * not a file.
   *
   * @param url The path to include when searching the classpath.
   */
  public static void add( URL url )
    throws IOException, NoSuchMethodException, IllegalAccessException,
           InvocationTargetException {
    Method method = CLASS_LOADER.getDeclaredMethod( "addURL", PARAMETERS );
    method.setAccessible( true );
    method.invoke( getClassLoader(), new Object[]{ url } );
  }

  private static URLClassLoader getClassLoader() {
    return (URLClassLoader)ClassLoader.getSystemClassLoader();
  }
}

Ссылка больше не работает: http: // форумы .sun.com / thread.jspa? threadID = 300557

Пример использования

В следующем примере в путь к классам добавляется / home / user / dev / java / app / build / com / package во время выполнения:

try {
  ClassPathUpdater.add( "/home/user/dev/java/app/build/com/package/Filename.class" );
}
catch( Exception e ) {
  e.printStackTrace();
}
13
ответ дан 30 November 2019 в 16:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: