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?
Still have not found any way around this issue:
Here's a log from today showing a little more:
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.
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