ОДНА native library в разных ClassLoader'ах
От: spbAngel  
Дата: 18.09.06 16:49
Оценка:
Вопрос подкупает своей глупостью. Как загрузить одну native-библиотеку в разных classloader'ах?

Знаю, что нельзя, но... Но проект построен так, что, одна бибилиотека используется набором плагинов, которые загружаются в разных classloader'ах. Плодить библиотеки нельзя — пусть она и небольшая, но заранее не известно, сколько плагинов будет создано (они "создаются" динамически).

Подскажите какую-нибудь хитрость. Или глупость.

P.S. http://java.sun.com/docs/books/jni/html/design.html#8628 (описание ограничения на загрузку, как я понял... )
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: ОДНА native library в разных ClassLoader'ах
От: Аноним  
Дата: 19.09.06 08:16
Оценка: +1
A>Вопрос подкупает своей глупостью. Как загрузить одну native-библиотеку в разных classloader'ах?

A>Знаю, что нельзя, но... Но проект построен так, что, одна бибилиотека используется набором плагинов, которые загружаются в разных classloader'ах. Плодить библиотеки нельзя — пусть она и небольшая, но заранее не известно, сколько плагинов будет создано (они "создаются" динамически).


A>Подскажите какую-нибудь хитрость. Или глупость.


A>P.S. http://java.sun.com/docs/books/jni/html/design.html#8628 (описание ограничения на загрузку, как я понял... )


А обязательно её загружать 2 раза?
Может, после того, как её кто-то загрузил ей могут пользоваться все?
Re[2]: ОДНА native library в разных ClassLoader'ах
От: ekaterma  
Дата: 19.09.06 09:53
Оценка:
Здравствуйте, Аноним, Вы писали:

A>>Вопрос подкупает своей глупостью. Как загрузить одну native-библиотеку в разных classloader'ах?


A>>Знаю, что нельзя, но... Но проект построен так, что, одна бибилиотека используется набором плагинов, которые загружаются в разных classloader'ах. Плодить библиотеки нельзя — пусть она и небольшая, но заранее не известно, сколько плагинов будет создано (они "создаются" динамически).


A>>Подскажите какую-нибудь хитрость. Или глупость.


A>>P.S. http://java.sun.com/docs/books/jni/html/design.html#8628 (описание ограничения на загрузку, как я понял... )


А>А обязательно её загружать 2 раза?

А>Может, после того, как её кто-то загрузил ей могут пользоваться все?

Одно из решений — это переписать "разные classloader-ы" таким образом, чтобы они делегировали загрузку
класса, в котором инициализируется native библиотека, одному специальному загрузчику (скажем NativeLoader).

Подробно почитать про загрузчики можно здесь: http://blogs.sun.com/vmrobot/category/Class%2BLoading

-katya
Re[2]: ОДНА native library в разных ClassLoader'ах
От: dshe  
Дата: 19.09.06 12:55
Оценка:
Здравствуйте, Аноним, Вы писали:

A>>Вопрос подкупает своей глупостью. Как загрузить одну native-библиотеку в разных classloader'ах?


A>>Знаю, что нельзя, но... Но проект построен так, что, одна бибилиотека используется набором плагинов, которые загружаются в разных classloader'ах. Плодить библиотеки нельзя — пусть она и небольшая, но заранее не известно, сколько плагинов будет создано (они "создаются" динамически).


A>>Подскажите какую-нибудь хитрость. Или глупость.


A>>P.S. http://java.sun.com/docs/books/jni/html/design.html#8628 (описание ограничения на загрузку, как я понял... )


А>А обязательно её загружать 2 раза?

А>Может, после того, как её кто-то загрузил ей могут пользоваться все?

Нет не могут.

Впрочем, можно попробовать такой еще вариант: библиотека загружаются не сама, а ее временная копия, которая создается на каждую попытку загрузить библиотеку. Что-то типа такого:
package nat;

public class Native {
    static {
        System.load(copyTemporary("native.dll"));
    }

    public static String copyTemporary(String filename) {
        File source = new File(filename);
        try {
            File target = File.createTempFile("lib", null);
            target.deleteOnExit();
            FileInputStream is = new FileInputStream(source);
            try {
                FileOutputStream os = new FileOutputStream(target);
                try {
                    int b;
                    while ((b = is.read()) != -1)
                        os.write(b);
                } finally {
                    os.close();
                }
            } finally {
                is.close();
            }
            return target.getPath();
        } catch (IOException exc) {
            throw new RuntimeException("cannot copy " + source + " to " + target, exc);
        }
    }

    public native void func();
}


Этот подход позволяет загружать одну библиотеку несколькими класслоадерами сохраняя при этом изоляцию. Но при этом надо предусмотреть еще механизм удаления временных файлов и иметь ввиду, что расход памяти будет больше, чем в том случае, когда библиотека загружается один раз самым корневым класслоадером.
--
Дмитро
Re[3]: ОДНА native library в разных ClassLoader'ах
От: spbAngel  
Дата: 09.10.06 11:33
Оценка:
Здравствуйте, ekaterma, Вы писали:

E>Одно из решений — это переписать "разные classloader-ы" таким образом, чтобы они делегировали загрузку

E>класса, в котором инициализируется native библиотека, одному специальному загрузчику (скажем NativeLoader).

E>Подробно почитать про загрузчики можно здесь: http://blogs.sun.com/vmrobot/category/Class%2BLoading


не помогло — native библиотека требует классы, которые загруженны не в NativeLoader, а в каждом из "разных classloader-ов" (plug-in'ы). Запрос из native, на подгрузку классов приходит такой (только имя необходимого класса), что не понятно, какой "classloader делегировал загрузку" и соответственно из какого дергать необходимые классы.

Да и JNI, вроде кэширует загруженные классы. Если 2 раза вызвать FindClass(char*) с одинаковыми параметрами, то второй вызов не вылетит в java. А надо бы — допускается, что это уже другой plug-in может быть
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: ОДНА native library в разных ClassLoader'ах
От: spbAngel  
Дата: 09.10.06 11:33
Оценка:
Здравствуйте, dshe, Вы писали:

D>Впрочем, можно попробовать такой еще вариант: библиотека загружаются не сама, а ее временная копия, которая создается на каждую попытку загрузить библиотеку. Что-то типа такого:

D>
D>package nat;

D>public class Native {
D>    static {
D>        System.load(copyTemporary("native.dll"));
D>    }

D>    public static String copyTemporary(String filename) {
D>        File source = new File(filename);
D>        try {
D>            File target = File.createTempFile("lib", null);
D>            target.deleteOnExit();
D>            FileInputStream is = new FileInputStream(source);
D>            try {
D>                FileOutputStream os = new FileOutputStream(target);
D>                try {
D>                    int b;
D>                    while ((b = is.read()) != -1)
D>                        os.write(b);
D>                } finally {
D>                    os.close();
D>                }
D>            } finally {
D>                is.close();
D>            }
D>            return target.getPath();
D>        } catch (IOException exc) {
D>            throw new RuntimeException("cannot copy " + source + " to " + target, exc);
D>        }
D>    }

D>    public native void func();
D>}
D>


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


Спасибо, вот только что делать, если подобный подход недопустим — запрещено плодить сущьности. Да и проблемы возможны. Если библиотека сохраняет своё состояния (в C++, я что-то подобное видел), то работа с копиями может привести к странным результатам — у каждой библиотеки будет своё состояние
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: ОДНА native library в разных ClassLoader'ах
От: dshe  
Дата: 23.10.06 07:46
Оценка:
Здравствуйте, spbAngel, Вы писали:

A>Здравствуйте, dshe, Вы писали:


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


A>Спасибо, вот только что делать, если подобный подход недопустим — запрещено плодить сущьности. Да и проблемы возможны. Если библиотека сохраняет своё состояния (в C++, я что-то подобное видел), то работа с копиями может привести к странным результатам — у каждой библиотеки будет своё состояние


На мой взгляд к странным результатам может привести то, если бы библиотеки, загруженные разными класслоадерами, имели общее состояние. Статические переменные java классов, загруженные разными класслоадерами, ведь не одни и те же, а разные. Собственно, ограничение на загрузку библиотеки разными класслоадерами было введено из-за того, что изолировать статические данные библиотеки толком никак не получается. Даже в том примере, который я привел, если native.dll загружает another.dll, то несмотря на то, возможна загрузка нескольких копий native.dll, another.dll загрузится только один раз, и следовательно, ее статические переменные будут общими для всех класслоадеров.
--
Дмитро
Re[4]: ОДНА native library в разных ClassLoader'ах
От: dshe  
Дата: 23.10.06 07:55
Оценка:
Здравствуйте, spbAngel, Вы писали:

A>Здравствуйте, ekaterma, Вы писали:


E>>Одно из решений — это переписать "разные classloader-ы" таким образом, чтобы они делегировали загрузку

E>>класса, в котором инициализируется native библиотека, одному специальному загрузчику (скажем NativeLoader).

E>>Подробно почитать про загрузчики можно здесь: http://blogs.sun.com/vmrobot/category/Class%2BLoading


A>не помогло — native библиотека требует классы, которые загруженны не в NativeLoader, а в каждом из "разных classloader-ов" (plug-in'ы). Запрос из native, на подгрузку классов приходит такой (только имя необходимого класса), что не понятно, какой "classloader делегировал загрузку" и соответственно из какого дергать необходимые классы.


A>Да и JNI, вроде кэширует загруженные классы. Если 2 раза вызвать FindClass(char*) с одинаковыми параметрами, то второй вызов не вылетит в java. А надо бы — допускается, что это уже другой plug-in может быть


FindClass загружает классы системным класслоадером. Чаще всего именно это и нужно. А для того, чтобы загрузить класс другим класслоадером (как, например, в твоем случае), необходимо вызвать java.lang.ClassLoader.loadClass (или даже java.lang.ClassLoader.loadClassInternal) при помощи CallXXXMethod.
--
Дмитро
Re[5]: ОДНА native library в разных ClassLoader'ах
От: spbAngel  
Дата: 23.10.06 13:03
Оценка:
Здравствуйте, dshe, Вы писали:

D>На мой взгляд к странным результатам может привести то, если бы библиотеки, загруженные разными класслоадерами, имели общее состояние. Статические переменные java классов, загруженные разными класслоадерами, ведь не одни и те же, а разные. Собственно, ограничение на загрузку библиотеки разными класслоадерами было введено из-за того, что изолировать статические данные библиотеки толком никак не получается. Даже в том примере, который я привел, если native.dll загружает another.dll, то несмотря на то, возможна загрузка нескольких копий native.dll, another.dll загрузится только один раз, и следовательно, ее статические переменные будут общими для всех класслоадеров.


А мне показалось, что вы предлагали копировать исходную библиотеку во "временные библиотеки", для нужд каждого classloader'а. Тогда и состояния будут различными, ведь реальные dll-файлы разные. Или не будут? Каюсь — я не проверял
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: ОДНА native library в разных ClassLoader'ах
От: spbAngel  
Дата: 23.10.06 13:06
Оценка:
dshe, я давненько открыл более топик с более подробным вопросом:
ОДНА native library в разных ClassLoader'ах (подробный вопрос)
Автор: spbAngel
Дата: 10.10.06
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.