#445 Static wrapper method wrapping native is not optimized-away

closed-works-for-me
5
2013-03-20
2012-05-17
Mihai Preda
No

Using Proguard 4.8beta1, on Linux. Configuration attached.

class N {
private native static void b(int img);
static void deleteJpeg(int img) { b(img); }
}

External calls of the form N.deleteJpeg() should be optimized by removing the wrapping, calling directly to the native method. The deleteJpeg() method should dissapear. Instead, deleteJpeg is renamed, but kept.

v.N -> v.N:
void b(int) -> b
17:18:void deleteJpeg(int) -> a

See also: http://blog.javia.org/android-obfuscating-the-jni-surface-layer/

Cheers,

Discussion

  • Mihai Preda
    Mihai Preda
    2012-05-17

    configuration file

     
    Attachments
  • Mihai Preda
    Mihai Preda
    2012-05-17

    The "private" on the native method is not significant, dropping it doesn't change the behavior.

     
  • Eric Lafortune
    Eric Lafortune
    2012-05-17

    ProGuard can currently remove a method by inlining it.
    However, the native method can't be inlined, because it is native.
    The static method may still be inlined wherever it is called, if it satisfies a number of conditions (most importantly, no static initializer with side-effects in its class).

    So this is not a bug, but detecting the wrapper method could be a new feature.

     
  • Eric Lafortune
    Eric Lafortune
    2012-05-17

    • assigned_to: nobody --> lafortune
    • priority: 5 --> 4
    • status: open --> open-works-for-me
     
  • Mihai Preda
    Mihai Preda
    2012-05-18

    OK, here is what I found:

    Usually the "static wrapper" is correctly inlined and disappears, as it should. Thus in general it works as intended.

    But when using
    -keepclasseswithmembernames class * { native <methods>; }
    the non-native static wrapper method is renamed, but kept. It does not vanish anymore as it did in the previous case.

    I agree that this is more a "lost optimization" than a bug, i.e. the generated code is nevertheless correct.

    In my case I tried various -keep variants, but I did not find a solution which:
    - keeps the class containing native methods with unchanged name.
    - keeps the native methods with unchanged names.
    - inlines and completely removes the wrapper methods.

    As a workaround in my situation I used "-applymapping" instead of wrappers, to directly rename the native methods (i.e. sort of I eliminated the need for the wrapper methods).

    It would be interesting to see if the
    -keepclasseswithmembernames class * { native <methods>; }
    disabling the elimination of the inlinable methods is the intended behavior for it. But you may close this issue as you see fit.

    thanks!

     
  • Eric Lafortune
    Eric Lafortune
    2013-03-20

    • Status: open-works-for-me --> closed-works-for-me
    • Priority: 4 --> 5