sventon subversion web client - http://www.sventon.org
[show recent changes]
 
  Help
Rev: HEAD (16683) - svn://svn.freehep.org/svn / freehep / branches / freehep-aidajni-3.2.x / simpleJNI.c
Show File - simpleJNI.c  [show properties]
Search for Help
spinner
/*
  File:    simple.c
  
  Description:  Sample code showing how to spin a new thread off to start the JVM
                        while using the primordial thread to run the AppKits main runloop.
                        
  Copyright:   � Copyright 2003 Apple Computer, Inc. All rights reserved.
  
  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  }


feed icon

sventon 2.5.1