Menu

#550 Unable to access Java class variables even when kept and found in seeds.txt

v4.7
open-works-for-me
None
5
2015-02-08
2014-11-15
Gerry Reno
No

Using Android SDK API 19
$ java -jar $ANDROID_SDK/tools/proguard/lib/proguard.jar
ProGuard, version 4.7

We posted the problem over on StackOverflow as well:
http://stackoverflow.com/questions/26942587/how-to-preserve-class-variables-accessed-from-jni-when-using-proguard

I've read through the manual -keep options but my JNI code is getting SIGSEGV when it accesses any of my Java class variables.

V/MyClass:native:my_native_method(30592): entered
I/DEBUG   (18752): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (18752): Build fingerprint: 'samsung/DEVICE/DEVICE:ANDROIDVERSION/XXXXXX/XXXXXX:user/release-keys'
I/DEBUG   (18752): pid: 30592, tid: 30619  >>> com.example <<<
I/DEBUG   (18752): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0000000c
I/DEBUG   (18752):  r0 413f5890  r1 409b1fc8  r2 00000000  r3 00000001
I/DEBUG   (18752):  r4 1d400256  r5 00000000  r6 5ca8fa80  r7 1d400256
I/DEBUG   (18752):  r8 5ca8fbe8  r9 56c6cea0  10 00000000  fp 5ca8fbfc
I/DEBUG   (18752):  ip 409ad030  sp 5ca8fa10  lr 400c4260  pc 40950524  cpsr 60000030
I/DEBUG   (18752):  d0  0000006442c80000  d1  3ff0000042c80000
I/DEBUG   (18752):  d2  0000000000000000  d3  43ec000043a60000
I/DEBUG   (18752):  d4  0000000000000000  d5  0000000000000000
I/DEBUG   (18752):  d6  00000000c2600000  d7  3f8000003f800000
I/DEBUG   (18752):  d8  43ec000044930000  d9  44084000448d0000
I/DEBUG   (18752):  d10 0000000000000000  d11 0000000000000000
I/DEBUG   (18752):  d12 0000000000000000  d13 0000000000000000
I/DEBUG   (18752):  d14 0000000000000000  d15 0000000000000000
I/DEBUG   (18752):  scr 60000010

By adding some log statements I could see that this happens whenever the native code accesses one of the Java class variables.

At first I tried:

-keep class com.example.MyClass {
    String mystring1;
    static String mystring2;
    byte[] mybytearray1;
    ...
}

I've even tried this in my proguard-project.txt:

-keep class com.example.MyClass {
    *;
}

But still I get SIGSEGV in my JNI library.

I looked in bin/proguard/seeds.txt and the variables ARE in there.

But something goes wrong.

The code runs perfectly until I enable ProGuard.

UPDATE: In researching this I am wondering whether the requirement about Android GC being able to relocate pointers is affecting ProGuard. In my native C code I have this:

JNIEXPORT jint JNICALL  Java_com_example_MyClass_my_1native_1method(
    JNIEnv* env,
    jobject thizz)
{
    jobject thiz = (*env)->NewGlobalRef(env,thizz); // prevent newer GC from relocating pointer

Could this be the source of the problem for ProGuard?

Discussion

  • Gerry Reno

    Gerry Reno - 2014-11-24

    Still have not found any way around this issue:

    Here's a log from today showing a little more:

    V/MyClass:native:my_native_method(10353): entered
    F/libc    (10353): Fatal signal 11 (SIGSEGV) at 0x0000000c (code=1), thread 10383 (AsyncTask #3)
    I/DEBUG   (  124): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    I/DEBUG   (  124): Build fingerprint: 'google/mysid/DEVICE:ANDROIDVERSION/XXXXXX/XXXXXX:user/release-keys'
    I/DEBUG   (  124): Revision: '10'
    I/DEBUG   (  124): pid: 10353, tid: 10383, name: AsyncTask #3  >>> com.example <<<
    I/DEBUG   (  124): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0000000c
    I/DEBUG   (  124):     r0 41500a90  r1 00000000  r2 00000001  r3 40892508
    I/DEBUG   (  124):     r4 1d5002c6  r5 00000000  r6 5f725af0  r7 1d5002c6
    I/DEBUG   (  124):     r8 5f725c50  r9 5888cea0  sl 5884c3d0  fp 5f725c64
    I/DEBUG   (  124):     ip 00000000  sp 5f725a80  lr 4082e287  pc 4082f7a0  cpsr 60000030
    I/DEBUG   (  124):     d0  6e6f435044522f6e  d1  6574737973796565
    I/DEBUG   (  124):     d2  6f637064722f7363  d3  726f637463656e74
    I/DEBUG   (  124):     d4  44525f65726f6374  d5  7463656e6e6f4350
    I/DEBUG   (  124):     d6  6b315f646e65735f  d7  73315f646b636f6e
    I/DEBUG   (  124):     d8  0000000000000000  d9  0000000000000000
    I/DEBUG   (  124):     d10 0000000000000000  d11 0000000000000000
    I/DEBUG   (  124):     d12 0000000000000000  d13 0000000000000000
    I/DEBUG   (  124):     d14 0000000000000000  d15 0000000000000000
    I/DEBUG   (  124):     d16 0000000000000000  d17 0000000000000000
    I/DEBUG   (  124):     d18 0000000000000000  d19 0000000000000000
    I/DEBUG   (  124):     d20 000000004f4f4f4f  d21 0000000000000000
    I/DEBUG   (  124):     d22 0707070703030303  d23 0000001600000016
    I/DEBUG   (  124):     d24 00b100b100b100b1  d25 0100010001000100
    I/DEBUG   (  124):     d26 0100010001000100  d27 0100010001000100
    I/DEBUG   (  124):     d28 0100010001000100  d29 0100010001000100
    I/DEBUG   (  124):     d30 0002f8ac0002f8ac  d31 0002f8ac0002f8ac
    I/DEBUG   (  124):     scr 60000090
    I/DEBUG   (  124): 
    I/DEBUG   (  124): backtrace:
    I/DEBUG   (  124):     #00  pc 0004b7a0  /system/lib/libdvm.so
    I/DEBUG   (  124):     #01  pc 00033397  /data/app-lib/com.example-1/libexample.so
    I/DEBUG   (  124):     #02  pc 00033e6b  /data/app-lib/com.example-1/libexample.so (Java_com.example_MyClass_my_1native_1method+62)
    I/DEBUG   (  124):     #03  pc 0001e290  /system/lib/libdvm.so (dvmPlatformInvoke+112)
    I/DEBUG   (  124):     #04  pc 0004d411  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396)
    I/DEBUG   (  124):     #05  pc 0004f56f  /system/lib/libdvm.so (dvmResolveNativeMethod(unsigned int const*, JValue*, Method const*, Thread*)+174)
    I/DEBUG   (  124):     #06  pc 000276a0  /system/lib/libdvm.so
    I/DEBUG   (  124):     #07  pc 0002b57c  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
    I/DEBUG   (  124):     #08  pc 0005fc31  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
    I/DEBUG   (  124):     #09  pc 0005fc5b  /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
    I/DEBUG   (  124):     #10  pc 000547d7  /system/lib/libdvm.so
    I/DEBUG   (  124):     #11  pc 0000e3d8  /system/lib/libc.so (__thread_entry+72)
    I/DEBUG   (  124):     #12  pc 0000dac4  /system/lib/libc.so (pthread_create+160)
    I/DEBUG   (  124): 
    I/DEBUG   (  124): stack:
    I/DEBUG   (  124):          5f725a40  00000000  
    I/DEBUG   (  124):          5f725a44  395b133c  
    I/DEBUG   (  124):          5f725a48  00000000  
    I/DEBUG   (  124):          5f725a4c  5f3f52ed  /data/app-lib/com.example-1/libexample.so
    I/DEBUG   (  124):          5f725a50  415428a8  /dev/ashmem/dalvik-heap (deleted)
    I/DEBUG   (  124):          5f725a54  408282a9  /system/lib/libdvm.so (dvmThrowExceptionFmt(ClassObject*, char const*, ...)+16)
    I/DEBUG   (  124):          5f725a58  4088dc98  /system/lib/libdvm.so
    I/DEBUG   (  124):          5f725a5c  1d5002c6  
    I/DEBUG   (  124):          5f725a60  408921b0  /system/lib/libdvm.so
    I/DEBUG   (  124):          5f725a64  1d5002c6  
    I/DEBUG   (  124):          5f725a68  41500a90  /dev/ashmem/dalvik-heap (deleted)
    I/DEBUG   (  124):          5f725a6c  4082e287  /system/lib/libdvm.so (dvmDecodeIndirectRef(Thread*, _jobject*)+178)
    I/DEBUG   (  124):          5f725a70  1d5002c6  
    I/DEBUG   (  124):          5f725a74  00000000  
    I/DEBUG   (  124):          5f725a78  df0027ad  
    I/DEBUG   (  124):          5f725a7c  00000000  
    I/DEBUG   (  124):     #00  5f725a80  58867a40  
    I/DEBUG   (  124):          5f725a84  5884c3c0  
    I/DEBUG   (  124):          5f725a88  00000000  
    I/DEBUG   (  124):          5f725a8c  4082f7cd  /system/lib/libdvm.so
    I/DEBUG   (  124):          5f725a90  5f725bec  
    I/DEBUG   (  124):          5f725a94  5f31d399  /data/app-lib/com.example-1/libexample.so
    I/DEBUG   (  124):     #01  5f725a98  1d5002c6  
    I/DEBUG   (  124):          5f725a9c  5f3f52ed  /data/app-lib/com.example-1/libexample.so
    I/DEBUG   (  124):          5f725aa0  00000000  
    I/DEBUG   (  124):          5f725aa4  5f725ac0  
    I/DEBUG   (  124):          5f725aa8  1d5002c6  
    I/DEBUG   (  124):          5f725aac  00000004  
    I/DEBUG   (  124):          5f725ab0  5888cea8  
    I/DEBUG   (  124):          5f725ab4  5f31de6f  /data/app-lib/com.example-1/libexample.so (Java_com.example_MyClass_my_1native_1method+66)
    I/DEBUG   (  124):     #02  5f725ab8  00000002  
    I/DEBUG   (  124):          5f725abc  5f725ac0  
    I/DEBUG   (  124):          5f725ac0  00000000  
    I/DEBUG   (  124):          5f725ac4  00000000  
    I/DEBUG   (  124):          5f725ac8  00000000  
    I/DEBUG   (  124):          5f725acc  00000000  
    I/DEBUG   (  124):          5f725ad0  00000000  
    I/DEBUG   (  124):          5f725ad4  00000000  
    I/DEBUG   (  124):          5f725ad8  00000000  
    I/DEBUG   (  124):          5f725adc  00000000  
    I/DEBUG   (  124):          5f725ae0  00000000  
    I/DEBUG   (  124):          5f725ae4  00000000  
    I/DEBUG   (  124):          5f725ae8  00000000  
    I/DEBUG   (  124):          5f725aec  00000000  
    I/DEBUG   (  124):          5f725af0  587f6520  
    I/DEBUG   (  124):          5f725af4  5996c228  
    I/DEBUG   (  124):          ........  ........
    
     
  • Eric Lafortune

    Eric Lafortune - 2014-11-25

    You should indeed debug your native code, around line 62, to see which class, field, and/or method is retrieved. You should then indeed use the proper -keep options. The trace by itself does not provide sufficient information.

    In your configuration, "String" should be the fully qualified name "java.lang.Stirng".

    The wildcard "*" will match all fields and methods in the specified class. You should double-check the class name. If this -keep option is not sufficient, there must be other relevant classes to keep.

    ProGuard does not affect garbage collection or its interaction with native code.

    Note that this is not a bug in ProGuard. ProGuard does not consider any reflection in native code. It is up to the developer to preserve classes, fields, and methods that are accessed by reflection.

     
  • Eric Lafortune

    Eric Lafortune - 2014-11-25
    • status: open --> open-works-for-me
    • assigned_to: Eric Lafortune
     
  • Gerry Reno

    Gerry Reno - 2014-11-26

    When you said this should be working I went looking for more areas. This project involves a main project that incorporates a number of subprojects. It is one of the subproject libraries that calls the native library. I had put the -keep class *; preservation into this subproject's proguard-project.txt. I didn't think it needed to be put into the main project proguard file. But that was the problem. As soon as I duplicated the library subproject's -keep class statement in the main project proguard file then the SIGSEGV disappeared. It would be nice if proguard could make it unnecessary to duplicate entries like this.

     

    Last edit: Gerry Reno 2014-11-26

Log in to post a comment.

MongoDB Logo MongoDB