Question

I have a problem loading a native library using System.loadLibrary("my_shared_lib"); The problem is that this call never returns.

Here is the context :

In my project I have several static libraries built using the nkd-build script. Building them works well using this Android.mk for each .a lib I need:

**Android.mk used for static libs**

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := my_static_lib_1

# Include paths
LOCAL_C_INCLUDES := \
    $(PATH_TO_INCLUDES1) \
    $(PATH_TO_INCLUDES2)

# Sources
LOCAL_SRC_FILES := \
    my_source_1.cpp\
    my_source_11.cpp


# Target
include $(BUILD_STATIC_LIBRARY)

These static libraries contain of course only native (C++) sources, among with some JNI wrappers (callable from Java sources).

Once all static libraries (.a) are built, I want to build a shared library (.so) containing all the .a libs I need. Here is the Android.mk I'm using to build this shared library:

LOCAL_PATH := $(call my-dir)
#----------
# Static prebuilt libs 
#----------
#-- my_static_lib_1
include $(CLEAR_VARS)
LOCAL_MODULE    := my_static_lib_1
LOCAL_SRC_FILES := $(PATH_TO_LIBS)/my_static_lib_1.a
include $(PREBUILT_STATIC_LIBRARY)

#-- my_static_lib_2
include $(CLEAR_VARS)
LOCAL_MODULE    := my_static_lib_2
LOCAL_SRC_FILES := $(PATH_TO_LIBS)/my_static_lib_2.a
include $(PREBUILT_STATIC_LIBRARY)

#----------
# Building shared lib
#----------
include $(CLEAR_VARS)
LOCAL_MODULE := my_shared_lib

#-- Some of the .a static libs need these libs
LOCAL_LDLIBS := \
    -lz\
    -llog \
    $(PATH_TO_NDK_LIBS)\libstlport_static.a

#-- This variable is used to force libs to be included in the .so
LOCAL_WHOLE_STATIC_LIBRARIES := \
    my_static_lib_1\
    my_static_lib_2

include $(BUILD_SHARED_LIBRARY)

This builds me a perfect .so file, containing all the functions from the .a libs (I could check that using the nm command on the generated .so lib).

And to be complete, here is the .java file dynamically loading the .so lib:

public class MyClass
{
    static {
        Log.d("MYLOGS", "Loading...");
        System.loadLibrary("my_shared_lib");
        Log.d("MYLOGS", "Loaded.");
    }
    ...
}

Problems:

When I'm creating a new instance of MyClass, loadLibrary is called, but it never returns. I can see the Loading... log but never the Loaded. one. The logCat says Trying to load lib [...].so but that's all, the app freezes.

All of this works fine when I have only one static lib .a in my .so file. In that case, I can call my native code perfectly. But my project uses 8 .a files, and I got a freezed app because loadLibrary never ends in that case.

What is wrong with the loadLibrary call ? Do you have any idea ?

Thanks.

Était-ce utile?

La solution

I've found out what was wrong in my code.

Actually when the loadLibrary loads a .so library, it creates all the global variables/constants declared in the .so, including of course every global of every .a lib contained in the .so.

Some of these global are built through constructors executing some code. I've found out that in my .a libs architecture, this code was deadlocking at some point because it was called too early (some needed stuff didn't exist yet). I didn't expect it to be called at the loadLibrary time.

So if that can help anyone: keep in mind that the loadLibrary involves creating all the global objects contained in the .so lib that you're trying to load.

Not knowing that was my mistake.

Autres conseils

In general, when you build a shared library (.so), some kind of compiler options such as -fPIC are used to generate position-independent code. On the other hand, when you build a static library (.a), such an option is not used. Even if you pack static libraries into a shared library, binary code in the static libraries are not position-independent. It is the reason why loadLibrary() fails, I guess.

If I were you, I would avoid packing static libraries into a shared library and instead would compile all C++ files with -fPIC or something equivalent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top