Как я могу избежать вызова System.load дважды? - PullRequest
1 голос
/ 27 июля 2010

У меня есть класс, который вызывает встроенную функцию для получения информации о системе из ее CMOS. Класс имеет статический блок инициализации, который загружает библиотеку, содержащую нативную функцию, и выглядит примерно так:

package lib.sysid;

public class SysId
{
    private static native int getSysIdNative();
    private static final String SYS_ID_PATH = "libsysid.so";

    static
    {
        System.load(SYS_ID_PATH);
    }

    public static int getSysIdFromCMOS()
    {
        int returnValue = getSysIdNative();
    }
}

Согласно моему тестированию, метод работает нормально при первом его использовании, но если я вызову метод еще раз позже, блок статической инициализации также запускается, вызывая UnsatisfiedLinkError:

java.lang.UnsatisfiedLinkError: Native Library libsysid.so already loaded in another classloader

Как я могу избежать выполнения статическим блоком инициализации метода System.load(), если он уже был запущен?

В качестве альтернативы, есть ли способ попытаться «разгрузить» библиотеку, если она уже загружена перед повторным вызовом метода System.load()?

РЕДАКТИРОВАТЬ: как ни странно, если я окружаю вызов System.load() блоком try-catch, я все равно получаю UnsatisfiedLinkError, но на этот раз это происходит от фактического вызова getSysIdNative(). Я вижу следующую ошибку:

lib.sysid.SysId.getSysIdNative()I

Какого черта это «я», которое появляется? Я пытался прикрепить отладчик к этому коду, чтобы увидеть, где заполняется сообщение, но пока что я не увенчался успехом.

Ответы [ 2 ]

2 голосов
/ 27 июля 2010

Просто предположение, но я думаю, что единственный способ для одной JVM загрузить класс (и выполнить его статические инициализаторы) дважды - загрузить его с различными загрузчиками классов.Так что здесь может быть задействован второй загрузчик классов, о котором вы не знаете.Это применимо, если во второй раз действует другой (набор) загрузчик классов.

В «реальной» операционной системе java -verbose:class выдаст вам сообщения загрузчика, чтобы проверить это.Я не уверен, как вы будете проверять это во встроенной системе.Вы можете изменить getSysId() для печати (?) Или каким-либо образом сбросить ссылку на SysId.class.getClassLoader().

0 голосов
/ 27 июля 2010

Я думаю, что @Carl прав. Единственный способ, которым статический инициализатор может запускаться дважды в JVM, - это если класс загружается в несколько загрузчиков классов.

lib.sysid.SysId.getSysIdNative()I Какого черта это «Я», которое появляется?

Это просто. I основан на внутреннем представлении типов в сигнатурах, которое определяется форматом файла класса. В частности, I означает примитивный тип int; см. Class.getName () и т. д. Это соответствует типу возврата вашего метода.

(Немного странно, что эти имена примитивных типов иногда появляются в пространстве приложения, но они появляются. Другой случай, когда вы можете их видеть, это когда вы вызываете toString() в классе, который наследует реализацию метода от Object класс.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...