1 /*
2 * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
132 VM_ERROR,
133 VM_IF_SERVER_CLASS,
134 VM_IGNORE
135 };
136
137 struct vmdesc {
138 char *name;
139 int flag;
140 char *alias;
141 char *server_class;
142 };
143 static struct vmdesc *knownVMs = NULL;
144 static int knownVMsCount = 0;
145 static int knownVMsLimit = 0;
146
147 static void GrowKnownVMs();
148 static int KnownVMIndex(const char* name);
149 static void FreeKnownVMs();
150 static jboolean IsWildCardEnabled();
151
152 #define ARG_CHECK(n, f, a) if (n < 1) { \
153 JLI_ReportErrorMessage(f, a); \
154 printUsage = JNI_TRUE; \
155 *pret = 1; \
156 return JNI_TRUE; \
157 }
158
159 /*
160 * Running Java code in primordial thread caused many problems. We will
161 * create a new thread to invoke JVM. See 6316197 for more information.
162 */
163 static jlong threadStackSize = 0; /* stack size of the new thread */
164 static jlong maxHeapSize = 0; /* max heap size */
165 static jlong initialHeapSize = 0; /* inital heap size */
166
167 /*
168 * Entry point.
169 */
170 int
171 JLI_Launch(int argc, char ** argv, /* main argc, argc */
172 int jargc, const char** jargv, /* java args */
173 int appclassc, const char** appclassv, /* app classpath */
174 const char* fullversion, /* full version defined */
175 const char* dotversion, /* dot version defined */
176 const char* pname, /* program name */
177 const char* lname, /* launcher name */
293 /* set the -Dsun.java.launcher.* platform properties */
294 SetJavaLauncherPlatformProps();
295
296 return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
297 }
298 /*
299 * Always detach the main thread so that it appears to have ended when
300 * the application's main method exits. This will invoke the
301 * uncaught exception handler machinery if main threw an
302 * exception. An uncaught exception handler cannot change the
303 * launcher's return code except by calling System.exit.
304 *
305 * Wait for all non-daemon threads to end, then destroy the VM.
306 * This will actually create a trivial new Java waiter thread
307 * named "DestroyJavaVM", but this will be seen as a different
308 * thread from the one that executed main, even though they are
309 * the same C thread. This allows mainThread.join() and
310 * mainThread.isAlive() to work as expected.
311 */
312 #define LEAVE() \
313 if ((*vm)->DetachCurrentThread(vm) != 0) { \
314 JLI_ReportErrorMessage(JVM_ERROR2); \
315 ret = 1; \
316 } \
317 (*vm)->DestroyJavaVM(vm); \
318 return ret \
319
320 #define CHECK_EXCEPTION_NULL_LEAVE(e) \
321 if ((*env)->ExceptionOccurred(env)) { \
322 JLI_ReportExceptionDescription(env); \
323 LEAVE(); \
324 } \
325 if ((e) == NULL) { \
326 JLI_ReportErrorMessage(JNI_ERROR); \
327 LEAVE(); \
328 }
329
330 #define CHECK_EXCEPTION_LEAVE(rv) \
331 if ((*env)->ExceptionOccurred(env)) { \
332 JLI_ReportExceptionDescription(env); \
333 ret = (rv); \
334 LEAVE(); \
335 }
336
337 int JNICALL
338 JavaMain(void * _args)
339 {
340 JavaMainArgs *args = (JavaMainArgs *)_args;
341 int argc = args->argc;
342 char **argv = args->argv;
343 int mode = args->mode;
344 char *what = args->what;
345 InvocationFunctions ifn = args->ifn;
346
347 JavaVM *vm = 0;
348 JNIEnv *env = 0;
349 jclass mainClass = NULL;
350 jclass appClass = NULL; // actual application class being launched
351 jmethodID mainID;
352 jobjectArray mainArgs;
353 int ret = 0;
354 jlong start, end;
355
417 *
418 * Hence, future work should either:
419 * 1) Correct the local parsing code and verify that the
420 * Main-Class attribute gets properly passed through
421 * all environments,
422 * 2) Remove the vestages of maintaining main_class through
423 * the environment (and remove these comments).
424 *
425 * This method also correctly handles launching existing JavaFX
426 * applications that may or may not have a Main-Class manifest entry.
427 */
428 mainClass = LoadMainClass(env, mode, what);
429 CHECK_EXCEPTION_NULL_LEAVE(mainClass);
430 /*
431 * In some cases when launching an application that needs a helper, e.g., a
432 * JavaFX application with no main method, the mainClass will not be the
433 * applications own main class but rather a helper class. To keep things
434 * consistent in the UI we need to track and report the application main class.
435 */
436 appClass = GetApplicationClass(env);
437 NULL_CHECK(appClass);
438 /*
439 * PostJVMInit uses the class name as the application name for GUI purposes,
440 * for example, on OSX this sets the application name in the menu bar for
441 * both SWT and JavaFX. So we'll pass the actual application class here
442 * instead of mainClass as that may be a launcher or helper class instead
443 * of the application class.
444 */
445 PostJVMInit(env, appClass, vm);
446 /*
447 * The LoadMainClass not only loads the main class, it will also ensure
448 * that the main method's signature is correct, therefore further checking
449 * is not required. The main method is invoked here so that extraneous java
450 * stacks are not in the application stack trace.
451 */
452 mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
453 "([Ljava/lang/String;)V");
454 CHECK_EXCEPTION_NULL_LEAVE(mainID);
455
456 /* Build platform specific argument array */
457 mainArgs = CreateApplicationArgs(env, argv, argc);
|
1 /*
2 * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
132 VM_ERROR,
133 VM_IF_SERVER_CLASS,
134 VM_IGNORE
135 };
136
137 struct vmdesc {
138 char *name;
139 int flag;
140 char *alias;
141 char *server_class;
142 };
143 static struct vmdesc *knownVMs = NULL;
144 static int knownVMsCount = 0;
145 static int knownVMsLimit = 0;
146
147 static void GrowKnownVMs();
148 static int KnownVMIndex(const char* name);
149 static void FreeKnownVMs();
150 static jboolean IsWildCardEnabled();
151
152 #define ARG_CHECK(AC_arg_count, AC_failure_message, AC_questionable_arg) \
153 do { \
154 if (AC_arg_count < 1) { \
155 JLI_ReportErrorMessage(AC_failure_message, AC_questionable_arg); \
156 printUsage = JNI_TRUE; \
157 *pret = 1; \
158 return JNI_TRUE; \
159 } \
160 } while (JNI_FALSE)
161
162 /*
163 * Running Java code in primordial thread caused many problems. We will
164 * create a new thread to invoke JVM. See 6316197 for more information.
165 */
166 static jlong threadStackSize = 0; /* stack size of the new thread */
167 static jlong maxHeapSize = 0; /* max heap size */
168 static jlong initialHeapSize = 0; /* inital heap size */
169
170 /*
171 * Entry point.
172 */
173 int
174 JLI_Launch(int argc, char ** argv, /* main argc, argc */
175 int jargc, const char** jargv, /* java args */
176 int appclassc, const char** appclassv, /* app classpath */
177 const char* fullversion, /* full version defined */
178 const char* dotversion, /* dot version defined */
179 const char* pname, /* program name */
180 const char* lname, /* launcher name */
296 /* set the -Dsun.java.launcher.* platform properties */
297 SetJavaLauncherPlatformProps();
298
299 return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret);
300 }
301 /*
302 * Always detach the main thread so that it appears to have ended when
303 * the application's main method exits. This will invoke the
304 * uncaught exception handler machinery if main threw an
305 * exception. An uncaught exception handler cannot change the
306 * launcher's return code except by calling System.exit.
307 *
308 * Wait for all non-daemon threads to end, then destroy the VM.
309 * This will actually create a trivial new Java waiter thread
310 * named "DestroyJavaVM", but this will be seen as a different
311 * thread from the one that executed main, even though they are
312 * the same C thread. This allows mainThread.join() and
313 * mainThread.isAlive() to work as expected.
314 */
315 #define LEAVE() \
316 do { \
317 if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \
318 JLI_ReportErrorMessage(JVM_ERROR2); \
319 ret = 1; \
320 } \
321 if (JNI_TRUE) { \
322 (*vm)->DestroyJavaVM(vm); \
323 return ret; \
324 } \
325 } while (JNI_FALSE)
326
327 #define CHECK_EXCEPTION_NULL_LEAVE(CENL_exception) \
328 do { \
329 if ((*env)->ExceptionOccurred(env)) { \
330 JLI_ReportExceptionDescription(env); \
331 LEAVE(); \
332 } \
333 if ((CENL_exception) == NULL) { \
334 JLI_ReportErrorMessage(JNI_ERROR); \
335 LEAVE(); \
336 } \
337 } while (JNI_FALSE)
338
339 #define CHECK_EXCEPTION_LEAVE(CEL_return_value) \
340 do { \
341 if ((*env)->ExceptionOccurred(env)) { \
342 JLI_ReportExceptionDescription(env); \
343 ret = (CEL_return_value); \
344 LEAVE(); \
345 } \
346 } while (JNI_FALSE)
347
348 int JNICALL
349 JavaMain(void * _args)
350 {
351 JavaMainArgs *args = (JavaMainArgs *)_args;
352 int argc = args->argc;
353 char **argv = args->argv;
354 int mode = args->mode;
355 char *what = args->what;
356 InvocationFunctions ifn = args->ifn;
357
358 JavaVM *vm = 0;
359 JNIEnv *env = 0;
360 jclass mainClass = NULL;
361 jclass appClass = NULL; // actual application class being launched
362 jmethodID mainID;
363 jobjectArray mainArgs;
364 int ret = 0;
365 jlong start, end;
366
428 *
429 * Hence, future work should either:
430 * 1) Correct the local parsing code and verify that the
431 * Main-Class attribute gets properly passed through
432 * all environments,
433 * 2) Remove the vestages of maintaining main_class through
434 * the environment (and remove these comments).
435 *
436 * This method also correctly handles launching existing JavaFX
437 * applications that may or may not have a Main-Class manifest entry.
438 */
439 mainClass = LoadMainClass(env, mode, what);
440 CHECK_EXCEPTION_NULL_LEAVE(mainClass);
441 /*
442 * In some cases when launching an application that needs a helper, e.g., a
443 * JavaFX application with no main method, the mainClass will not be the
444 * applications own main class but rather a helper class. To keep things
445 * consistent in the UI we need to track and report the application main class.
446 */
447 appClass = GetApplicationClass(env);
448 NULL_CHECK_RETURN_VALUE(appClass, -1);
449 /*
450 * PostJVMInit uses the class name as the application name for GUI purposes,
451 * for example, on OSX this sets the application name in the menu bar for
452 * both SWT and JavaFX. So we'll pass the actual application class here
453 * instead of mainClass as that may be a launcher or helper class instead
454 * of the application class.
455 */
456 PostJVMInit(env, appClass, vm);
457 /*
458 * The LoadMainClass not only loads the main class, it will also ensure
459 * that the main method's signature is correct, therefore further checking
460 * is not required. The main method is invoked here so that extraneous java
461 * stacks are not in the application stack trace.
462 */
463 mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
464 "([Ljava/lang/String;)V");
465 CHECK_EXCEPTION_NULL_LEAVE(mainID);
466
467 /* Build platform specific argument array */
468 mainArgs = CreateApplicationArgs(env, argv, argc);
|