sventon subversion web client - http://www.sventon.org |
[show recent changes] | |
Rev: HEAD (16683) - svn://svn.freehep.org/svn / freehep / branches / freehep-aidajni-3.2.x / simpleJNI.c |
Show File - simpleJNI.c [show properties] |
1 | /* |
2 | File: simple.c |
3 | |
4 | Description: Sample code showing how to spin a new thread off to start the JVM |
5 | while using the primordial thread to run the AppKits main runloop. |
6 | |
7 | Copyright: � Copyright 2003 Apple Computer, Inc. All rights reserved. |
8 | |
9 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
10 | ("Apple") in consideration of your agreement to the following terms, and your |
11 | use, installation, modification or redistribution of this Apple software |
12 | constitutes acceptance of these terms. If you do not agree with these terms, |
13 | please do not use, install, modify or redistribute this Apple software. |
14 | |
15 | In consideration of your agreement to abide by the following terms, and subject |
16 | to these terms, Apple grants you a personal, non-exclusive license, under Apple's |
17 | copyrights in this original Apple software (the "Apple Software"), to use, |
18 | reproduce, modify and redistribute the Apple Software, with or without |
19 | modifications, in source and/or binary forms; provided that if you redistribute |
20 | the Apple Software in its entirety and without modifications, you must retain |
21 | this notice and the following text and disclaimers in all such redistributions of |
22 | the Apple Software. Neither the name, trademarks, service marks or logos of |
23 | Apple Computer, Inc. may be used to endorse or promote products derived from the |
24 | Apple Software without specific prior written permission from Apple. Except as |
25 | expressly stated in this notice, no other rights or licenses, express or implied, |
26 | are granted by Apple herein, including but not limited to any patent rights that |
27 | may be infringed by your derivative works or by other works in which the Apple |
28 | Software may be incorporated. |
29 | |
30 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
31 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
32 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
33 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
34 | COMBINATION WITH YOUR PRODUCTS. |
35 | |
36 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
37 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
38 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
39 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
40 | OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
41 | (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
42 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
43 | |
44 | |
45 | */ |
46 | |
47 | #include <sys/stat.h> |
48 | #include <sys/resource.h> |
49 | #include <pthread.h> |
50 | #include <CoreFoundation/CoreFoundation.h> |
51 | #include "utils.h" |
52 | |
53 | /*Starts a JVM using the options,classpath,main class, and args stored in a VMLauchOptions structure */ |
54 | static void* startupJava(void *options) { |
55 | int result = 0; |
56 | JNIEnv* env; |
57 | JavaVM* theVM; |
58 | |
59 | VMLaunchOptions * launchOptions = (VMLaunchOptions*)options; |
60 | |
61 | /* default vm args */ |
62 | JavaVMInitArgs vm_args; |
63 | |
64 | /* |
65 | To invoke Java 1.4.1 or the currently preferred JDK as defined by the operating system (1.4.2 as of the |
66 | release of this sample and the release of Mac OS X 10.4) nothing changes in 10.4 vs 10.3 in that when a |
67 | JNI_VERSION_1_4 is passed into JNI_CreateJavaVM as the vm_args.version it returns the current preferred JDK. |
68 | |
69 | To specify the current preferred JDK in a family of JVM's, say the 1.5.x family, applications should set |
70 | the environment variable JAVA_JVM_VERSION to 1.5, and then pass JNI_VERSION_1_4 into JNI_CreateJavaVM as |
71 | the vm_args.version. To get a specific Java 1.5 JVM, say Java 1.5.0, set the environment variable |
72 | JAVA_JVM_VERSION to 1.5.0. For Java 1.6 it will be the same in that applications will need to set the |
73 | environment variable JAVA_JVM_VERSION to 1.6 to specify the current preferred 1.6 Java VM, and to get |
74 | a specific Java 1.6 JVM, say Java 1.6.1, set the environment variable JAVA_JVM_VERSION to 1.6.1. |
75 | |
76 | To make this sample bring up the current preferred 1.5 JVM, set the environment variable JAVA_JVM_VERSION |
77 | to 1.5 before calling JNI_CreateJavaVM as shown below. Applications must currently check for availability |
78 | of JDK 1.5 before requesting it. If your application requires JDK 1.5 and it is not found, it is your |
79 | responsibility to report an error to the user. To verify if a JVM is installed, check to see if the symlink, |
80 | or directory exists for the JVM in /System/Library/Frameworks/JavaVM.framework/Versions/ before setting the |
81 | environment variable JAVA_JVM_VERSION. |
82 | |
83 | If the environment variable JAVA_JVM_VERSION is not set, and JNI_VERSION_1_4 is passed into JNI_CreateJavaVM |
84 | as the vm_args.version, JNI_CreateJavaVM will return the current preferred JDK. Java 1.4.2 is the preferred |
85 | JDK as of the release of this sample and the release of Mac OS X 10.4. |
86 | */ |
87 | { |
88 | CFStringRef targetJVM = CFSTR("1.5"); |
89 | CFBundleRef JavaVMBundle; |
90 | CFURLRef JavaVMBundleURL; |
91 | CFURLRef JavaVMBundlerVersionsDirURL; |
92 | CFURLRef TargetJavaVM; |
93 | UInt8 pathToTargetJVM [PATH_MAX] = "\0"; |
94 | struct stat sbuf; |
95 | |
96 | |
97 | // Look for the JavaVM bundle using its identifier |
98 | JavaVMBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.JavaVM") ); |
99 | |
100 | if(JavaVMBundle != NULL) { |
101 | // Get a path for the JavaVM bundle |
102 | JavaVMBundleURL = CFBundleCopyBundleURL(JavaVMBundle); |
103 | CFRelease(JavaVMBundle); |
104 | |
105 | if(JavaVMBundleURL != NULL) { |
106 | // Append to the path the Versions Component |
107 | JavaVMBundlerVersionsDirURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,JavaVMBundleURL,CFSTR("Versions"),true); |
108 | CFRelease(JavaVMBundleURL); |
109 | |
110 | if(JavaVMBundlerVersionsDirURL != NULL) { |
111 | // Append to the path the target JVM's Version |
112 | TargetJavaVM = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,JavaVMBundlerVersionsDirURL,targetJVM,true); |
113 | CFRelease(JavaVMBundlerVersionsDirURL); |
114 | |
115 | if(TargetJavaVM != NULL) { |
116 | if(CFURLGetFileSystemRepresentation (TargetJavaVM,true,pathToTargetJVM,PATH_MAX )) { |
117 | // Check to see if the directory, or a sym link for the target JVM directory exists, and if so set the |
118 | // environment variable JAVA_JVM_VERSION to the target JVM. |
119 | if(stat((char*)pathToTargetJVM,&sbuf) == 0) { |
120 | // Ok, the directory exists, so now we need to set the environment var JAVA_JVM_VERSION to the CFSTR targetJVM |
121 | // We can reuse the pathToTargetJVM buffer to set the environement var. |
122 | if(CFStringGetCString(targetJVM,(char*)pathToTargetJVM,PATH_MAX,kCFStringEncodingUTF8)) |
123 | setenv("JAVA_JVM_VERSION", (char*)pathToTargetJVM,1); |
124 | } |
125 | } |
126 | CFRelease(TargetJavaVM); |
127 | } |
128 | } |
129 | } |
130 | } |
131 | } |
132 | |
133 | /* JNI_VERSION_1_4 is used on Mac OS X to indicate the 1.4.x and later JVM's */ |
134 | vm_args.version = JNI_VERSION_1_4; |
135 | vm_args.options = launchOptions->options; |
136 | vm_args.nOptions = launchOptions->nOptions; |
137 | vm_args.ignoreUnrecognized = JNI_TRUE; |
138 | |
139 | /* start a VM session */ |
140 | result = JNI_CreateJavaVM(&theVM, (void**)&env, &vm_args); |
141 | |
142 | if ( result != 0 ) { |
143 | fprintf(stderr, "[JavaAppLauncher Error] Error starting up VM.\n"); |
144 | exit(result); |
145 | return NULL; |
146 | } |
147 | |
148 | /* Find the main class */ |
149 | jclass mainClass = (*env)->FindClass(env, launchOptions->mainClass); |
150 | if ( mainClass == NULL ) { |
151 | (*env)->ExceptionDescribe(env); |
152 | result = -1; |
153 | goto leave; |
154 | } |
155 | |
156 | /* Get the application's main method */ |
157 | jmethodID mainID = (*env)->GetStaticMethodID(env, mainClass, "main", |
158 | "([Ljava/lang/String;)V"); |
159 | if (mainID == NULL) { |
160 | if ((*env)->ExceptionOccurred(env)) { |
161 | (*env)->ExceptionDescribe(env); |
162 | } else { |
163 | fprintf(stderr, "[JavaAppLauncher Error] No main method found in specified class.\n"); |
164 | } |
165 | result = -1; |
166 | goto leave; |
167 | } |
168 | |
169 | /* Build argument array */ |
170 | jobjectArray mainArgs = NewPlatformStringArray(env, (char **)launchOptions->args, launchOptions->numberOfArgs); |
171 | if (mainArgs == nil) { |
172 | (*env)->ExceptionDescribe(env); |
173 | goto leave; |
174 | } |
175 | |
176 | /* or create an empty array of java.lang.Strings to pass in as arguments to the main method |
177 | jobjectArray mainArgs = (*env)->NewObjectArray(env, 0, |
178 | (*env)->FindClass(env, "java/lang/String"), NULL); |
179 | if (mainArgs == 0) { |
180 | result = -1; |
181 | goto leave; |
182 | } |
183 | */ |
184 | |
185 | /* Invoke main method passing in the argument object. */ |
186 | (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); |
187 | if ((*env)->ExceptionOccurred(env)) { |
188 | (*env)->ExceptionDescribe(env); |
189 | result = -1; |
190 | goto leave; |
191 | } |
192 | |
193 | leave: |
194 | freeVMLaunchOptions(launchOptions); |
195 | (*theVM)->DestroyJavaVM(theVM); |
196 | exit(result); |
197 | return NULL; |
198 | } |
199 | |
200 | /* call back for dummy source used to make sure the CFRunLoop doesn't exit right away */ |
201 | /* This callback is called when the source has fired. */ |
202 | void sourceCallBack ( void *info ) {} |
203 | |
204 | /* The following code will spin a new thread off to start the JVM |
205 | while using the primordial thread to run the main runloop. |
206 | */ |
207 | int main(int argc, const char **argv) |
208 | { |
209 | CFRunLoopSourceContext sourceContext; |
210 | |
211 | /* Start the thread that runs the VM. */ |
212 | pthread_t vmthread; |
213 | |
214 | /* Parse the args */ |
215 | VMLaunchOptions * launchOptions = NewVMLaunchOptions(argc, argv); |
216 | |
217 | /* Set our name for the Application Menu to our Main class */ |
218 | setAppName(launchOptions->mainClass); |
219 | |
220 | /* create a new pthread copying the stack size of the primordial pthread */ |
221 | struct rlimit limit; |
222 | size_t stack_size = 0; |
223 | int rc = getrlimit(RLIMIT_STACK, &limit); |
224 | if (rc == 0) { |
225 | if (limit.rlim_cur != 0LL) { |
226 | stack_size = (size_t)limit.rlim_cur; |
227 | } |
228 | } |
229 | |
230 | pthread_attr_t thread_attr; |
231 | pthread_attr_init(&thread_attr); |
232 | pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM); |
233 | pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); |
234 | if (stack_size > 0) { |
235 | pthread_attr_setstacksize(&thread_attr, stack_size); |
236 | } |
237 | |
238 | /* Start the thread that we will start the JVM on. */ |
239 | pthread_create(&vmthread, &thread_attr, startupJava, launchOptions); |
240 | pthread_attr_destroy(&thread_attr); |
241 | |
242 | /* Create a a sourceContext to be used by our source that makes */ |
243 | /* sure the CFRunLoop doesn't exit right away */ |
244 | sourceContext.version = 0; |
245 | sourceContext.info = NULL; |
246 | sourceContext.retain = NULL; |
247 | sourceContext.release = NULL; |
248 | sourceContext.copyDescription = NULL; |
249 | sourceContext.equal = NULL; |
250 | sourceContext.hash = NULL; |
251 | sourceContext.schedule = NULL; |
252 | sourceContext.cancel = NULL; |
253 | sourceContext.perform = &sourceCallBack; |
254 | |
255 | /* Create the Source from the sourceContext */ |
256 | CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate (NULL, 0, &sourceContext); |
257 | |
258 | /* Use the constant kCFRunLoopCommonModes to add the source to the set of objects */ |
259 | /* monitored by all the common modes */ |
260 | CFRunLoopAddSource (CFRunLoopGetCurrent(),sourceRef,kCFRunLoopCommonModes); |
261 | |
262 | /* Park this thread in the runloop */ |
263 | CFRunLoopRun(); |
264 | |
265 | return 0; |
266 | } |
sventon 2.5.1