Ответы пользователя по тегу Java
  • Загрузка двух нативных библиотек через JNI под линуксом?

    Zorkus
    @Zorkus Автор вопроса
    В итоге я решил эту проблему следующим образом: оказалось, что обе библиотеки надо линковать с флагом -Wl,soname. Поскольку у меня не было доступа к исходником сторонней библиотеки, я уговорил ее создателя прислать мне объектные файлы, и слинковал ее сам :)

    Всем спасибо за помощь! :)
    Ответ написан
    Комментировать
  • Загрузка двух нативных библиотек через JNI под линуксом?

    Zorkus
    @Zorkus Автор вопроса
    По какой-то гнусной причине, в манах на kernel.org не написано, пытается ли dlopen() с флагом RTLD_NOLOAD найти .so файл в файловой системе в процессе проверки, загружена ли такая библиотека, или нет.

    Все, что написано:

    RTLD_NOLOAD (since glibc 2.2)
    Don't load the library. This can be used to test if the library is
    already resident (dlopen() returns NULL if it is not, or the library's
    handle if it is resident). This flag can also be used to promote the
    flags on a library that is already loaded. For example, a library that
    was previously loaded with RTLD_LOCAL can be reopened with
    RTLD_NOLOAD | RTLD_GLOBAL. This flag is not specified in POSIX.1-2001.
    Ответ написан
    Комментировать
  • Загрузка двух нативных библиотек через JNI под линуксом?

    Zorkus
    @Zorkus Автор вопроса
    Покопался немного в коде, интересуют комменты от разработчиков JVM. Надо может быть отдельный пост написать про это.

    Итак, все знают что загружаются нативные библиотеки через класс java.lang.ClassLoader, и и точка перехода в нативный код — java.lang.ClassLoader.NativeLibrary.load.

    Смотрим jdk/j2se/src/share/native/java/lang/ClassLoader.c, видим:

    ....
    JNIEXPORT void JNICALL
    Java_java_lang_ClassLoader_00024NativeLibrary_load
    (JNIEnv *env, jobject this, jstring name)
    {
    const char *cname;
    jint jniVersion;
    jthrowable cause;
    void * handle;

    if (!initIDs(env))
    return;

    cname = JNU_GetStringPlatformChars(env, name, 0);
    if (cname == 0)
    return;
    handle = JVM_LoadLibrary(cname);
    if (handle) {
    // разнообразные проверки и обрабока исключений
    }
    ...


    Смотрим где определена функция JVM_LoadLibrary, пролистав хедеры jvm.h, находим что-то похожее на то, что нам нужно в файле jdk/hotspot/src/share/vm/prims/jvm.cpp:

    JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name))
    //%note jvm_ct
    JVMWrapper2("JVM_LoadLibrary (%s)", name);
    char ebuf[1024];
    void *load_result;
    {
    ThreadToNativeFromVM ttnfvm(thread);
    load_result = hpi::dll_load(name, ebuf, sizeof ebuf);
    }
    if (load_result == NULL) {
    char msg[1024];
    jio_snprintf(msg, sizeof msg, "%s: %s", name, ebuf);
    ...
    Handle h_exception =
    Exceptions::new_exception(thread,
    vmSymbols::java_lang_UnsatisfiedLinkError(),
    msg, Exceptions::unsafe_to_utf8);

    THROW_HANDLE_0(h_exception);
    }


    Т.е. функция dll_load уже похожа на ту, где должен идти натуральный вызов системных функций для загрузки (POSIX/WINAPI), иначе это уже слишком много уровней получается. Смотрим файл jdk/hotspot/src/os/os/linux/vm/os_linux.cpp: видим:

    // Loads .dll/.so and
    // in case of error it checks if .dll/.so was built for the
    // same architecture as Hotspot is running on

    void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
    {
    void * result= ::dlopen(filename, RTLD_LAZY);
    if (result != NULL) {
    // Successful loading
    return result;
    }


    Ха! Т.е. shared object-ы таки загружаются без добавочного флага RTLD_NOLOAD! Т.е. JVM не проверяет, перед загрузкой, загружена соотв. либа или еще нет?

    Для сравнения посмотрим аналогичный код Windows, смотрим файл os_windows.cpp:

    // Loads .dll/.so and
    // in case of error it checks if .dll/.so was built for the
    // same architecture as Hotspot is running on
    void * os::dll_load(const char *name, char *ebuf, int ebuflen)
    {
    void * result = LoadLibrary(name);
    if (result != NULL)
    {
    return result;
    }


    А теперь смотрим на документация в LoadLibrary здесь: msdn.microsoft.com/en-us/library/windows/desktop/ms682586.aspx

    If a DLL with the same module name is already loaded in memory, the system checks only for redirection and a manifest before resolving to the loaded DLL, no matter which directory it is in. The system does not search for the DLL.

    Т.е. поведение для линукса и виндовса будет различное в данном случае.

    Читаем:
    Ответ написан
    Комментировать
  • Загрузка двух нативных библиотек через JNI под линуксом?

    Zorkus
    @Zorkus Автор вопроса
    Еще небольшое пояснение. В коде все было верно и так, это в пост на хабре закралась ошибка.

    libA.so — моя библиотека, libB.so — чужая библиотека, А слинкована с параметров -L /path-to-lib-B -lB, из явы сначала грузится B, потом А. И это не работает под линуксом (под Windows аналогичный трюк работает!), логгинг показывает следующее — System.loadLibrary(B); — работает и загружает libB.so, затем вызов System.loadLibrary(A) падает c сообщением что невозможно найти файла libB.so (хотя, эта библиотека уже загружена в память процесса).

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

    Пока моя гипотеза (надо посмотреть нативный код в JDK который собственно грузит библиотеки, как я понимаю это dlopen() под линуксом), при загрузке библиотеки libA.so dlopen не проверяет перед тем, как попытаться выполнить динамическую линковку библиотеки A «а загружена ли B в память процесса или нет», проверять это можно передавая в dlopen flag RTLD_NOLOAD. Возможно, еще, что это внутреннее поведение рантайм-линкера под юниксом, на который JVM никак повлиять не может.

    Так или иначе — я тоже был уверен, что это должно работать, но почему-то не работает.
    Ответ написан
    Комментировать
  • Загрузка двух нативных библиотек через JNI под линуксом?

    Zorkus
    @Zorkus Автор вопроса
    Да, кстати, очень извиняюсь, но у меня там была опечатка (опечатка именно в посте, в коде все было правильно! :)

    В посте вместо:

    На самом деле, конечно, обратный порядок:
    Вместо
    static {
    System.loadLibrary(A);
    System.loadLibrary(B);
    }

    должно быть:

    static {
    System.loadLibrary(B);
    System.loadLibrary(A);
    }

    И соотв, порядок загрузки в объяснения ниже тоже другой. Попровил пост.
    Ответ написан
    Комментировать
  • Загрузка двух нативных библиотек через JNI под линуксом?

    Zorkus
    @Zorkus Автор вопроса
    Это понятно, вопрос в том, почему под виндой нативный линкер не пытается ее взять вовсе (так как она загружена уже в память процесса JVM), а под юниксом пытается :)

    Судя по коду в ClassLoader.java, на по крайней мере на уровне java код JDK и под виндой и под линуксом ссылки на кешированные библиотеки (private static Stack nativeLibraryContext = new Stack();) хранятся в любом случае одинаково.
    Ответ написан
    Комментировать
  • Почему в Java нет памяти типа stack?

    Zorkus
    @Zorkus
    Тут основной момент такой- стек, это же вещь локальная для конкретного потока, потому в сложных приложениях выделять много памяти на стеке из одного потока вряд ли имеет смысла.

    Тем более, дефолтный размер стека для одного потока в Java небольшой, 512кб по умолчанию.
    Ответ написан
    Комментировать
  • Почему в Java нет памяти типа stack?

    Zorkus
    @Zorkus
    По моему, все примитивные типы и их врапперы, по крайней мере локальные в пределах методов, в яве выделяются в стеке текущего потока.

    Но совершенно точно, JVM активно использует внутри стек для размещения объектов.
    Ответ написан
    Комментировать
  • Запуск большого количества параллельных задач в отдельных песочницах?

    Zorkus
    @Zorkus Автор вопроса
    Использование JVM мне тут нравится всем, кроме одного — память. В моем понимании, при запуске для таких целей, оверхед под памяти у JVM будет много больше, чем у Питона.
    Ответ написан
    Комментировать
  • Java - "Отрицательный" возврат

    Zorkus
    @Zorkus
    Поддерживаю, используйте либо return null, либо определите специальный тип NullObject, и возвращайте его в этом случае.

    en.wikipedia.org/wiki/Null_Object_pattern
    Ответ написан
    Комментировать
  • J2EE и высокие нагрузки?

    Zorkus
    @Zorkus
    Сказанное про стек J2EE тоже верно, для веб-хайлоада часто применяются только сервлет контейнеры (Tomcat / Jetty), с лоадбалансингом, + часто выделенный апач/nginx как фронтэнд для статики.

    Если же это не-веб хайлоад (банки, биржи), так там часто стек J2EE и ну нужен вовсе, зачем? Там нужна J2SE, multithreading, Spring для каркаса приложения, и какой нибудь hadoop (или что-то самописное) для распределения вычислений по нодам.
    Ответ написан
    Комментировать
  • J2EE и высокие нагрузки?

    Zorkus
    @Zorkus
    Примеры нагруженных проектов из топа Алексы, юзающие Java: Amazon, eBay, LinkedIn, Google.

    Очень много на Java в банках (особенно в инвестиционной аналитике), в биржевых приложениях, как уже было сказано.
    Ответ написан
    1 комментарий
  • В какую сторону лучше двигаться с JAVA

    Zorkus
    @Zorkus
    Java востребована и больше всего платят (среди Java-разработчиков) в области нагруженных Enterprise web и всяких нагруженных систем обработки данных.

    Из нагруженных сайтов с миллионами посетителей с Back-End на Java (по крайней мере частично) — это Amazon, LinkedIn, eBay.

    Системы обработки данных — это биржевые систимы (требуется ultra-low latency), банковские системы (распределенные системы для расчета рисков в инвестиционном банкинге), геоданные (в связке с O-Spatial, как было связано), обработка статистических данных, всевозможные кластерные вычисления и InMemoryDataGrid-ы, наконец та отрасль где работаю я — Data Mining в области Retail индустрии.
    Ответ написан
    Комментировать
  • Идеи по поводу развития блога Java

    Zorkus
    @Zorkus
    В целом я поддериживаю идею — заранее публиковать своеобразный «тизер», что ли, и спрашивать -кому было бы интересно прочитать.

    Потому что на самом деле хорошая глубокая техническая статья — это 1-3 дня на исследования, эксперименты и гуглинг, и день на собственно на написание статьи.
    Ответ написан
  • Идеи по поводу развития блога Java

    Zorkus
    @Zorkus
    У меня есть в черновиках несколько статей по Java и JVM тематике, но все никак руки не дойдут их допилить и выложить, извините :(

    Был бы признателен если кто прокомментирует — чего бы больше хотелось почитать. Тогда я как то приоретизирую и постараюсь найти время в ближайшее время.

    1) Java — Atomitcs и неблокирующие алгоритмы в Java, concurrency.
    2) Java — как работает внутри Reflection.
    3) Groovy — как работают внутри замыкания, мемоизация замыканий, рекурсивные замыкания и лямбды.
    4) Метапрограммирование в Groovy — AST-трансформации и Meta-Object Protocol.
    Ответ написан
    6 комментариев
  • Вопрос посвящен литературе по Java?

    Zorkus
    @Zorkus
    ИМхо оригинал написан лучше. А последнего издания я вообще не припоминаю чтобы видел в переведенном виде.
    Ответ написан
    Комментировать