Вопрос подкупает своей глупостью. Как загрузить одну native-библиотеку в разных classloader'ах?
Знаю, что нельзя, но... Но проект построен так, что, одна бибилиотека используется набором плагинов, которые загружаются в разных classloader'ах. Плодить библиотеки нельзя — пусть она и небольшая, но заранее не известно, сколько плагинов будет создано (они "создаются" динамически).
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'ах
Здравствуйте, Аноним, Вы писали:
A>>Вопрос подкупает своей глупостью. Как загрузить одну native-библиотеку в разных classloader'ах?
A>>Знаю, что нельзя, но... Но проект построен так, что, одна бибилиотека используется набором плагинов, которые загружаются в разных classloader'ах. Плодить библиотеки нельзя — пусть она и небольшая, но заранее не известно, сколько плагинов будет создано (они "создаются" динамически).
A>>Подскажите какую-нибудь хитрость. Или глупость.
A>>P.S. http://java.sun.com/docs/books/jni/html/design.html#8628 (описание ограничения на загрузку, как я понял... )
А>А обязательно её загружать 2 раза? А>Может, после того, как её кто-то загрузил ей могут пользоваться все?
Одно из решений — это переписать "разные classloader-ы" таким образом, чтобы они делегировали загрузку
класса, в котором инициализируется native библиотека, одному специальному загрузчику (скажем NativeLoader).
Здравствуйте, Аноним, Вы писали:
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'ах
Здравствуйте, 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'ах
Здравствуйте, 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'ах
Здравствуйте, spbAngel, Вы писали:
A>Здравствуйте, dshe, Вы писали:
D>>Этот подход позволяет загружать одну библиотеку несколькими класслоадерами сохраняя при этом изоляцию. Но при этом надо предусмотреть еще механизм удаления временных файлов и иметь ввиду, что расход памяти будет больше, чем в том случае, когда библиотека загружается один раз самым корневым класслоадером.
A>Спасибо, вот только что делать, если подобный подход недопустим — запрещено плодить сущьности. Да и проблемы возможны. Если библиотека сохраняет своё состояния (в C++, я что-то подобное видел), то работа с копиями может привести к странным результатам — у каждой библиотеки будет своё состояние
На мой взгляд к странным результатам может привести то, если бы библиотеки, загруженные разными класслоадерами, имели общее состояние. Статические переменные java классов, загруженные разными класслоадерами, ведь не одни и те же, а разные. Собственно, ограничение на загрузку библиотеки разными класслоадерами было введено из-за того, что изолировать статические данные библиотеки толком никак не получается. Даже в том примере, который я привел, если native.dll загружает another.dll, то несмотря на то, возможна загрузка нескольких копий native.dll, another.dll загрузится только один раз, и следовательно, ее статические переменные будут общими для всех класслоадеров.
--
Дмитро
Re[4]: ОДНА native library в разных ClassLoader'ах
Здравствуйте, 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'ах
Здравствуйте, 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'ах