Как я могу постараться не называть System.load дважды?

У меня есть класс, который вызывает собственную функцию для получения информации о системе от ее 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

Какого черта то, что "I", который обнаруживается? Я попытался присоединить отладчик к этому коду для наблюдения, где сообщение заполняется, но до сих пор я не был успешен.

1
задан troyal 26 July 2010 в 20:42
поделиться

2 ответа

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

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

2
ответ дан 2 September 2019 в 22:44
поделиться

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

lib.sysid.SysId.getSysIdNative () I Что, черт возьми, за то «я», которое появляется?

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

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

0
ответ дан 2 September 2019 в 22:44
поделиться
Другие вопросы по тегам:

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