JNI wrapper for NSSavePanel

Steve Hannah steve at weblite.ca
Sun Oct 7 18:42:44 PDT 2012


OK.  I have made the following change to the method:


JNIEXPORT jstring JNICALL Java_ca_weblite_mactools_Sandbox_saveDialog

(JNIEnv *env, jobject jthis, jstring title, jstring extension){

    JNF_COCOA_ENTER(<#env#>);

    return JNFNSToJavaString(env, @"/Users/shannah/Downloads/out2.pdf");

    JNF_COCOA_EXIT(env);

    return NULL;
}

It still crashes.  Here are some of the crash details.

Process:         JavaAppLauncher [13397]
Path:
 /Users/USER/Documents/*/MyApp.app/Contents/MacOS/JavaAppLauncher
Identifier:      ca.myidentifier
Version:         1.9.32 (1.9.32)
Code Type:       X86-64 (Native)
Parent Process:  launchd [140]
User ID:         501

Date/Time:       2012-10-07 18:20:23.789 -0700
OS Version:      Mac OS X 10.8.1 (12B19)
Report Version:  10

Crashed Thread:  25  Java: Thread-2

Exception Type:  EXC_BAD_ACCESS (SIGABRT)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000020

VM Regions Near 0x20:
-->
    __TEXT                 0000000103466000-000000010346a000 [   16K]
r-x/rwx SM=COW
 /Users/USER/Documents/*/MyApp.app/Contents/MacOS/JavaAppLauncher

Application Specific Information:
abort() called


And the thread that crashed:

Thread 25 Crashed:: Java: Thread-2
0   libsystem_kernel.dylib         0x00007fff8a043212 __pthread_kill + 10
1   libsystem_c.dylib             0x00007fff87e93b34 pthread_kill + 90
2   libsystem_c.dylib             0x00007fff87ed7dfa abort + 143
3   libjvm.dylib                   0x0000000103a12a9f os::abort(bool) + 25
4   libjvm.dylib                   0x0000000103aff35e
VMError::report_and_die() + 2306
5   libjvm.dylib                   0x0000000103a14193 JVM_handle_bsd_signal
+ 1073
6   libsystem_c.dylib             0x00007fff87e8092a _sigtramp + 26
7   libobjc.A.dylib               0x00007fff898d33ee objc_retain + 14
8   ???                           0x0000000104267f90 0 + 4364599184
9   ???                           0x000000010425c333 0 + 4364550963
10  ???                           0x00000001042564f7 0 + 4364526839
11  libjvm.dylib                   0x00000001038ea083
JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*,
Thread*) + 557
12  libjvm.dylib                   0x00000001038e9e50
JavaCalls::call(JavaValue*, methodHandle, JavaCallArguments*, Thread*) + 40
13  libjvm.dylib                   0x0000000103a53062
Reflection::invoke(instanceKlassHandle, methodHandle, Handle, bool,
objArrayHandle, BasicType, objArrayHandle, bool, Thread*) + 2506
14  libjvm.dylib                   0x0000000103a534ba
Reflection::invoke_method(oopDesc*, Handle, objArrayHandle, Thread*) + 360
15  libjvm.dylib                   0x000000010391a99b JVM_InvokeMethod + 352
16  ???                           0x0000000104267f90 0 + 4364599184
17  ???                           0x000000010425c333 0 + 4364550963
18  ???                           0x000000010425c333 0 + 4364550963
19  ???                           0x000000010425c9e1 0 + 4364552673
20  ???                           0x000000010425c333 0 + 4364550963
21  ???                           0x000000010425c333 0 + 4364550963
22  ???                           0x000000010425c333 0 + 4364550963
23  ???                           0x000000010425c333 0 + 4364550963
24  ???                           0x000000010425c333 0 + 4364550963
25  ???                           0x000000010425c333 0 + 4364550963
26  ???                           0x000000010425c333 0 + 4364550963
27  ???                           0x000000010425c333 0 + 4364550963
28  ???                           0x000000010425c333 0 + 4364550963
29  ???                           0x000000010425c333 0 + 4364550963
30  ???                           0x000000010425c333 0 + 4364550963
31  ???                           0x000000010425c333 0 + 4364550963
32  ???                           0x000000010425c333 0 + 4364550963
33  ???                           0x000000010425c333 0 + 4364550963
34  ???                           0x000000010425c333 0 + 4364550963
35  ???                           0x000000010425c333 0 + 4364550963
36  ???                           0x000000010425c158 0 + 4364550488
37  ???                           0x000000010425c158 0 + 4364550488
38  ???                           0x000000010425c806 0 + 4364552198
39  ???                           0x00000001042564f7 0 + 4364526839
40  libjvm.dylib                   0x00000001038ea083
JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*,
Thread*) + 557
41  libjvm.dylib                   0x00000001038ea560
JavaCalls::call_virtual(JavaValue*, KlassHandle, Symbol*, Symbol*,
JavaCallArguments*, Thread*) + 256
42  libjvm.dylib                   0x00000001038ea69a
JavaCalls::call_virtual(JavaValue*, Handle, KlassHandle, Symbol*, Symbol*,
Thread*) + 74
43  libjvm.dylib                   0x000000010391d504
thread_entry(JavaThread*, Thread*) + 169
44  libjvm.dylib                   0x0000000103ad4f74
JavaThread::thread_main_inner() + 134
45  libjvm.dylib                   0x0000000103ad6413 JavaThread::run() +
369
46  libjvm.dylib                   0x0000000103a12fc1 java_start(Thread*) +
173
47  libsystem_c.dylib             0x00007fff87e92782 _pthread_start + 327
48  libsystem_c.dylib             0x00007fff87e7f1c1 thread_start + 13



I ran otool -L on the library to check that the JavaNativeFoundation was
being linked and it looks like it is.  It's output is as follows:

macbook-air-2:MacTools shannah$ otool -L libmactools.dylib
libmactools.dylib:
/usr/local/lib/JSandbox.dylib (compatibility version 1.0.0, current version
1.0.0)
/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework/Versions/A/JavaNativeFoundation
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility
version 1.0.0, current version 19.0.0)
/System/Library/Frameworks/JavaVM.framework/Versions/A/JavaVM
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
(compatibility version 45.0.0, current version 1187.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
(compatibility version 300.0.0, current version 945.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version
228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version
169.3.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
(compatibility version 150.0.0, current version 744.0.0)


Does this information provide any clues that I might be missing?

Thanks for all your help so far.

Best regards

Steve


On Sun, Oct 7, 2012 at 3:05 PM, Steve Hannah <steve at weblite.ca> wrote:



>
> This is not a valid C function based on the return type - in the case
>> where an error occurs, the return value of this function is undefined and
>> will likely be whatever garbage is left on the stack (isn't Xcode
>> warning/erroring about this like crazy???). You need a "return NULL;" at
>> the very end so that the JNI return value will be defined in the case where
>> you don't make it to the first return.
>>
>> Thanks for the tip, I'll add the null return and see if that helps.  (No
> Xcode didn't complain... no warnings, no errors, "build succeeded").
>
>>
>> Are you sure the library is even getting built and loaded? Can you make a
>> plain JNI function next to this one that contains nothing but a simple
>> "fprintf(stderr, "test\n");" in it? Call that first, and see if the library
>> is even loaded.
>>
>> Yes.  The library is getting built and loaded.  I have 2 other JNI
> methods that are working properly  (but only if I don't wrap them in
> JNF_COCOA_ENTER/EXIT).  In my java logging I output the string result of
> another one of the methods just before calling this one and it outputs fine.
>
>
>> Given my inexperience with XCode, I suspect that it could be a problem
>> with the way I'm building/linking the JNI library.  The fact that calls to
>> JNFNSToJavaString() work makes me thing that the JavaNativeFoundation is
>> correctly linked (?).
>>
>>
>> It may be getting hauled in by Java 7 itself, and not explicitly linked.
>> If you don't have the JavaNativeFounation.framework explicitly linked in
>> the target that builds your library, that would also cause the compiler to
>> infer that the JNF_COCOA_ENTER/EXIT macros are actually functions, and
>> treat them as undeclared/unlinked entities.
>>
>> Run otool -L on your library, and make sure the full path to
>> JavaNativeFoundation.framework is printed out. If it isn't, you are only
>> picking up the symbols inside of it by accident.
>>
>
> Thanks... I'll try that.
>
> Best regards
>
> Steve
>
>
>>
>> Regards,
>> Mike Swingler
>> Apple Inc.
>>
>> Any other suggestions or tips, much appreciated.
>>
>>
>> Best regards
>>
>> Steve
>>
>>
>>>> JNF_COCOA_ENTER/EXIT do more than just setup an autorelease pool - they
>>>> also catch ObjC exceptions and re-throw them as Java runtime exceptions.
>>>>
>>>> Do you have the backtrace of where you are crashing when using
>>>> JNF_COCOA_ENTER/EXIT?
>>>>
>>> I do, but I'm having difficulty making heads or tails from it.  I'm also
>>> struggling with getting logging information out on the Java side as I'm
>>> working on a Mountain Lion machine and I can't find where System.out and
>>> System.err are logged by default... and the sandbox is making it difficult
>>> for me to set a log location manually... (anything that runs or fails
>>> before or during the setting of a custom log location is not logged).
>>>
>>>
>>> I think (but I'm not certain) that this is the way it is now on Lion and
>>> Mountain Lion - output logged to stdout/stderr directly (including the JVM
>>> System.out/err) just goes to /dev/null unless you run the primary
>>> executable from a shell or some other parent process that gives it a TTY.
>>> Otherwise, the only thing that gets logged to the system console comes
>>> through ASL, like NSLog(). Of course, I may be completely off on this, but
>>> perhaps this is explaining what you are seeing.
>>>
>>> Also, are you doing anything special to run this JNI method on the main
>>>> AppKit thread (or are you using SWT)?
>>>
>>> Ah.. I hadn't thought of that, but yes.  I'm overriding the
>>> java.awt.FileDialog class's setVisible() method to display this as a modal
>>> dialog.
>>>
>>>
>>>> If not, you may want to use +[JNFRunLoop
>>>> performOnMainThreadWaiting:withBlock:], which will block the current
>>>> thread, run your block on the main thread (safe for AppKit), and then
>>>> continue execution of your Java thread when the block returns.
>>>>
>>>
>>> I'll give this a shot.
>>>
>>> Thanks for the suggestions.
>>>
>>>
>>> No problem. Please do always think of the threading considerations when
>>> writing JNI. We try to let you not worry about exceptions and autorelease
>>> pools if you use JNF, but threading is still something you have to think
>>> through when you get JNI and Cocoa tangled together.
>>>
>>> Best of luck,
>>> Mike Swingler
>>> Apple Inc.
>>>
>>>
>>
>>
>> --
>> Steve Hannah
>> Web Lite Solutions Corp.
>>
>>
>>
>
>
> --
> Steve Hannah
> Web Lite Solutions Corp.
>
>


-- 
Steve Hannah
Web Lite Solutions Corp.


More information about the macosx-port-dev mailing list