New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 702703 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Mar 2017
Cc:
EstimatedDays: ----
NextAction: ----
OS: Android
Pri: 3
Type: Bug



Sign in to add a comment

JNI generator chokes on generative native calls with inner class as parameter

Project Member Reported by dgn@chromium.org, Mar 17 2017

Issue description

Moving from

class MostVisitedSites {
   interface Observer { ... }
   private native void nativeSetObserver(long nativeMostVisitedSites, Observer observer, ...);
}

To

interface MostVisitedSites {
   interface Observer { ... }
}

class MostVisitedSitesBridge implements MostVisitedSites {
   interface Observer { ... }
   private native void nativeSetObserver(long nativeMostVisitedSites, Observer observer, ...);
}


The code above compiles but crashes at runtime:


D/dalvikvm: Trying to load lib /data/data/org.chromium.chrome/incremental-install-files/lib/libchrome.cr.so 0x425eeb18
D/dalvikvm: Added shared lib /data/data/org.chromium.chrome/incremental-install-files/lib/libchrome.cr.so 0x425eeb18
E/dalvikvm: ERROR: couldn't find native method
E/dalvikvm: Requested: Lorg/chromium/chrome/browser/suggestions/MostVisitedSitesBridge;.nativeSetObserver:(JLorg/chromium/chrome/browser/suggestions/Observer;I)V
E/dalvikvm: Candidate: Lorg/chromium/chrome/browser/suggestions/MostVisitedSitesBridge;.nativeSetObserver:(JLorg/chromium/chrome/browser/suggestions/MostVisitedSites$Observer;I)V
E/chromium: [0317/154432.314259:ERROR:jni_generator_helper.h(38)] RegisterNatives failed in gen/chrome/browser/jni_headers/chrome/jni/MostVisitedSitesBridge_jni.h
E/chromium: [0317/154432.314376:ERROR:jni_registrar.cc(21)] MostVisitedSitesBridge failed registration!
W/dalvikvm: threadid=13: thread exiting with uncaught exception (group=0x41591ba8)
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3
E/AndroidRuntime: Process: org.chromium.chrome, PID: 18657
E/AndroidRuntime: java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime: 	at android.os.AsyncTask$3.done(AsyncTask.java:300)
E/AndroidRuntime: 	at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
E/AndroidRuntime: 	at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
E/AndroidRuntime: 	at java.util.concurrent.FutureTask.run(FutureTask.java:242)
E/AndroidRuntime: 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime: 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime: 	at java.lang.Thread.run(Thread.java:841)
E/AndroidRuntime: Caused by: java.lang.NoSuchMethodError: no static or non-static method "Lorg/chromium/chrome/browser/suggestions/MostVisitedSitesBridge;.nativeSetObserver(JLorg/chromium/chrome/browser/suggestions/Observer;I)V"
E/AndroidRuntime: 	at java.lang.Runtime.nativeLoad(Native Method)


I tried changing the native method declaration to use a qualified class name

private native void nativeSetObserver(long nativeMostVisitedSites, MostVisitedSites.Observer observer, ...);

That fails at compile time:


Working directory: /usr/local/ssd/clankium/src
ninja -j2000 -l150 -C out_android_gn/Debug chrome_public_apk_incremental
ninja: Entering directory `out_android_gn/Debug'
[2/105] ACTION //chrome/browser:jni_headers__jni_gen(//build/toolchain/android:android_clang_arm)
FAILED: gen/chrome/browser/jni_headers/chrome/jni/MostVisitedSitesBridge_jni.h 
python ../../base/android/jni_generator/jni_generator.py --depfile gen/chrome/browser/jni_headers__jni_gen.MostVisitedSitesBridge.d --input_file=../../chrome/android/java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java --optimize_generation=1 --ptr_type=long --output_dir gen/chrome/browser/jni_headers/chrome/jni --includes ../../../../../../../../base/android/jni_generator/jni_generator_helper.h --native_exports_optional
Traceback (most recent call last):
  File "../../base/android/jni_generator/jni_generator.py", line 1418, in <module>
    sys.exit(main(sys.argv))
  File "../../base/android/jni_generator/jni_generator.py", line 1411, in main
    GenerateJNIHeader(input_file, output_file, options)
  File "../../base/android/jni_generator/jni_generator.py", line 1318, in GenerateJNIHeader
    input_file, options)
  File "../../base/android/jni_generator/jni_generator.py", line 720, in CreateFromFile
    return JNIFromJavaSource(contents, fully_qualified_class, options)
  File "../../base/android/jni_generator/jni_generator.py", line 692, in __init__
    self.content = inl_header_file_generator.GetContent()
  File "../../base/android/jni_generator/jni_generator.py", line 788, in GetContent
    'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(),
  File "../../base/android/jni_generator/jni_generator.py", line 861, in GetJNINativeMethodsString
    return self.SubstituteNativeMethods(template)
  File "../../base/android/jni_generator/jni_generator.py", line 844, in SubstituteNativeMethods
    kmethods = self.GetKMethodsString(clazz)
  File "../../base/android/jni_generator/jni_generator.py", line 835, in GetKMethodsString
    ret += [self.GetKMethodArrayEntry(native)]
  File "../../base/android/jni_generator/jni_generator.py", line 1183, in GetKMethodArrayEntry
    True),
  File "../../base/android/jni_generator/jni_generator.py", line 343, in Signature
    items += [JniParams.JavaToJni(param.datatype) for param in params]
  File "../../base/android/jni_generator/jni_generator.py", line 312, in JavaToJni
    outer.replace('/', '.')))
SyntaxError: Inner class (MostVisitedSites.Observer) can not be used directly by JNI. Please import the outer class, probably:
import org.chromium.chrome.browser.suggestions.MostVisitedSites;
[4/105] ACTION //chrome/android:chrome_java__compile_java__javac(//build/toolchain/android:android_clang_arm)



My current workaround is to just declare the parameter as Object, but keeping the relative type safety would be preferred, or at least for documentation purposes. Can this be fixed in the generator?

CL for context: https://codereview.chromium.org/2754203004

 

Comment 1 by dgn@chromium.org, Mar 20 2017

As pointed out by torne@, the second error message suggests what should be done to fix the issue:

"Please import the outer class, probably:
import org.chromium.chrome.browser.suggestions.MostVisitedSites;"

The problem then is that since it's the same package, IDEs flag that as redundant imports and (depending on your setup) remove the line automatically, and presubmit treats it as an error.

There is already another official workaround for that issue though: @JNIAdditionalImport.

- Source: https://cs.chromium.org/chromium/src/base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java
- Sample usage: https://cs.chromium.org/chromium/src/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java?q=@jniadditionalimport

Comment 2 by torne@chromium.org, Mar 20 2017

Status: WontFix (was: Untriaged)
Yeah, the @JNIAdditionalImport workaround is kinda weird but it enables the generator to not have to be very smart about guessing where classes are. I don't think changing the generator to guess more here is worth it.

Sign in to add a comment