How would one create a custom JVM launcher? - java

There has been a history of "how to launch an application without a main method" questions, most stating something along the lines of "you can't". I noticed how JavaFX applications can now be launched simply by extending Application. I've been using a method similar to Application.launch(), but I've always seen the main method as boilerplate code in that situation. So I started looking for answers again.
I found this answer linking us to where we can learn about creating our own JVM launchers, but sadly the article no longer exists. I've spent quite a while looking for anything that might hint me on what I should do, but no results.
My Question
How would one create a custom JVM launcher to launch an application based on what is being extended? For example, imagine a project with 1 declared class:
class MyApplcation extends App {
}
No main method is needed for the project to be launched, since it extends App. This is not the question, although it is my target goal. The question is how could someone create a custom JVM launcher?
My guess is that it would involve using some kind of base, to give us a skeleton of some sort, but I'm not sure where to find such a thing.

How JavaFX Implements its Application Execution Model
JavaFX applications which contain no main method can be launched because of the implementation of JEP 153: Enhance the java command-line launcher to launch JavaFX applications.
This was modification of the openjdk launcher logic to check if the class to be launched extends Application, and, if so, call out to a JavaFX specific launcher which started up the Java runtime and associated threads, created a GUI window (in JavaFX terms a Stage), then, created an instance of the avaFX application and invoked init and start methods on the application as per the the JavaFX application lifecycle rules.
Tracing the implementation through in code:
main.c for JVM invokes JLILaunch in java.c
java.c looks for a Java class sun.launcher.LauncherHelper and calls into the java class using JNI, invoking the checkAndLoadMain function.
If the class to be launched has no main method, but does extend the JavaFX application class, a FXHelper class is created holding the launch parameters.
A reference to the FXHelper is returned to java.c via JNI.
java.c invokes the main method on the FXHelper via JNI.
The FXHelper uses reflection to invoke com.sun.javafx.application.LauncherImpl.launchApplication().
The JavaFX LauncherImpl will setup the application classloader, then first try to invoke a main() method on the main class of the application.
If there is no main() method, the JavaFX LauncherImpl will start up the JavaFX launcher thread.
On the launcher thread, the LauncherImpl will call init() on the JavaFX application.
On the JavaFX application thread, the LauncherImpl will create a new Stage (window) and pass it to the start method of the application.
When the last stage is closed or the JavaFX platform is exited, the stop method on the application is called by the LauncherImpl.
All the call traces return and the application exits because there is nothing more to do.
How you could customize the launcher
Grab a copy of the sun.launcher.LauncherHelper code.
Ignore the warning at the top of the code "This is NOT part of any API supported by Sun Microsystems. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice." and start modifying the code anyway.
Create your own version of the FXHelper which will invoke your own LauncherImpl rather than the JavaFX one (in the case that the target main application class extends your application framework class rather than the JavaFX one).
Write your own LauncherImpl that sets up the classloader for your application, creates an instance of your application class and invokes whatever launch entry points you want on your application type.
Run your applications, placing the hacked version of the sun.launcher.LauncherHelper and your LauncherImpl on the boot class path, so they get picked up instead of the default versions which ship the JDK.
Sample launch command, assuming the target application to be launched is com.mycompany.MyApplication:
java -Xbootclasspath/p <launcher class directory> com.mycompany.MyApplication

Related

How much code is visible to JVM?

As every java application needs the main method except the case of applets and web application where the main method is implemented by web container so as the main method is starting point of the program as we pass the name of the class including main with java command to execute it.
So my question is how much code is visible to JVM means does it sees the whole code or it loads classes or information it came across during execution of the program.
Maybe my question is out of context, but please clear it.
Java loads classes "on demand". As soon as you somehow "use" X, X.class is loaded. Please note: "using" is more than just "importing" within source code.
You can find a nice introduction to this topic here.
And, as Holger points out correctly: you have to distinguish between loading and initialization time.

Run Java application with minimal code (hiding the main-method) [duplicate]

There has been a history of "how to launch an application without a main method" questions, most stating something along the lines of "you can't". I noticed how JavaFX applications can now be launched simply by extending Application. I've been using a method similar to Application.launch(), but I've always seen the main method as boilerplate code in that situation. So I started looking for answers again.
I found this answer linking us to where we can learn about creating our own JVM launchers, but sadly the article no longer exists. I've spent quite a while looking for anything that might hint me on what I should do, but no results.
My Question
How would one create a custom JVM launcher to launch an application based on what is being extended? For example, imagine a project with 1 declared class:
class MyApplcation extends App {
}
No main method is needed for the project to be launched, since it extends App. This is not the question, although it is my target goal. The question is how could someone create a custom JVM launcher?
My guess is that it would involve using some kind of base, to give us a skeleton of some sort, but I'm not sure where to find such a thing.
How JavaFX Implements its Application Execution Model
JavaFX applications which contain no main method can be launched because of the implementation of JEP 153: Enhance the java command-line launcher to launch JavaFX applications.
This was modification of the openjdk launcher logic to check if the class to be launched extends Application, and, if so, call out to a JavaFX specific launcher which started up the Java runtime and associated threads, created a GUI window (in JavaFX terms a Stage), then, created an instance of the avaFX application and invoked init and start methods on the application as per the the JavaFX application lifecycle rules.
Tracing the implementation through in code:
main.c for JVM invokes JLILaunch in java.c
java.c looks for a Java class sun.launcher.LauncherHelper and calls into the java class using JNI, invoking the checkAndLoadMain function.
If the class to be launched has no main method, but does extend the JavaFX application class, a FXHelper class is created holding the launch parameters.
A reference to the FXHelper is returned to java.c via JNI.
java.c invokes the main method on the FXHelper via JNI.
The FXHelper uses reflection to invoke com.sun.javafx.application.LauncherImpl.launchApplication().
The JavaFX LauncherImpl will setup the application classloader, then first try to invoke a main() method on the main class of the application.
If there is no main() method, the JavaFX LauncherImpl will start up the JavaFX launcher thread.
On the launcher thread, the LauncherImpl will call init() on the JavaFX application.
On the JavaFX application thread, the LauncherImpl will create a new Stage (window) and pass it to the start method of the application.
When the last stage is closed or the JavaFX platform is exited, the stop method on the application is called by the LauncherImpl.
All the call traces return and the application exits because there is nothing more to do.
How you could customize the launcher
Grab a copy of the sun.launcher.LauncherHelper code.
Ignore the warning at the top of the code "This is NOT part of any API supported by Sun Microsystems. If you write code that depends on this, you do so at your own risk. This code and its internal interfaces are subject to change or deletion without notice." and start modifying the code anyway.
Create your own version of the FXHelper which will invoke your own LauncherImpl rather than the JavaFX one (in the case that the target main application class extends your application framework class rather than the JavaFX one).
Write your own LauncherImpl that sets up the classloader for your application, creates an instance of your application class and invokes whatever launch entry points you want on your application type.
Run your applications, placing the hacked version of the sun.launcher.LauncherHelper and your LauncherImpl on the boot class path, so they get picked up instead of the default versions which ship the JDK.
Sample launch command, assuming the target application to be launched is com.mycompany.MyApplication:
java -Xbootclasspath/p <launcher class directory> com.mycompany.MyApplication

Where is main() in Android?

I am new to Android, and was studying the framework and it compelled me to ask this question. Since we are extending Activity in Android, there has to be main somewhere in Activity or there is an hidden class that Activity implements that contains main.
I looked everywhere but couldn't find it. I would appreciate if any one could give a clear idea on it.
In core Java programs we need a main() method, because while executing the byte code the JVM will search for the main() method in the class and start executing there.
In the case of Android, the Dalvik Virtual Machine (After android 5.0 DVM is replaced by Android Runtime) is designed to find a class which is a subclass of Activity and which is set as a LAUNCHER to start the execution of the application from its onCreate() method, so there is no need of a main() method.
For more information see the life cycle of Activity.
Actually, the main() method is the Android framework class android.app.ActivityThread. This method creates the Main (UI) Thread for an OS process, sets up the Looper on it and starts the event loop.
The Android framework is responsible for creating and destroying OS processes, launching applications, starting activites, services and other components. The ActivityManager is part of the Android framework and it is responsible for coordinating and managing different components.
The architecture of Android is a bit different than you may be used to from stand-alone Java applications. The biggest difference is that all of your components (Activity, Service, BroadcastReceiver, etc.) do not necessarily run in the same OS process or in the same virtual machine (VM). It is possible to have components from a single application running in different OS processes and it is also possible to have components from different applications running in the same OS process. In traditional Java, the main() method is the method that is called by virtual machine after the OS process has been created and the virtual machine has completed its initialization.
Android uses the java language, but executes using a modified runtime model. As others have said, there is a manifest included in each package. The launchpoint is specified in this manifest. Go to the android site and do the basic tutorials. This will get you up and running with an understanding of create/deploy/run process and the basic app life cycle.
Read this blog entry to understand how an Android application starts:
During startup of the Android system the Linux kernel first calls the
process "init". init reads the files "/init.rc" and "init.device.rc".
"init.device.rc" is device specific, on the virtual device this file
is called "init.goldfish.rc".
init.rc starts the process "Zygote" via the program "/system/bin/app_process". Zygote loads the core Java classes and
performs initial processing of them. These classes can be reused by
Android application and therefore this step makes them faster to
start. Once the initial work of Zygote is done, the process listens to
a socket and waits for requests.
If you look in the ZygoteInit class, you'll find the main method.
As others have mentioned, this main() method is involved in setting up the Android app environment. As far as a developer is concerned, the starting point is the onCreate() method of the Launcher activity.
In Android, the OS uses Dalvik virtual machine. The main entry point to the execution of the application is encapsulated within the framework. You might want to take a look at "What is Android?"
In fact, each Activity in Android can be thought to be a single Application on its own with a lifecycle of its own.
onCreate() Method....See lifecycle of android class (Activity).....
http://developer.android.com/reference/android/app/Activity.html
You tell it which one to run on startup in the manifest file. There isn't a main() function because there doesn't have to be. main() may be a convention used for "regular" java apps, but it isn't for things like browser applets. The system creates the activity object and calls methods within it, which may or may not be called main. In this case, it's not.
onCreate is different from a main() method, and from a constructor, in that it can be called twice on a single activity, such as if the process is killed and the user navigates back to the activity. See this
Many things that you might think of as a Java "application" do not have their own main() method. For example, IIRC, servlets, WARs, and the like do not have main() methods -- the main() method, if there is one, is in the container.
When you start a new process to run a App/Service, finally in ActivityManagerService.java, there is:
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
Which finally calls Process.start. This is the same with the standard java, you pass in a class then the VM create a new process and execute main() of ActivityThread.java:
public static void main(String[] args) {
......
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
The main function will trigger some action that send IPC message to notify Activity Manager that the process has started successfully, then after notifying the process that initiate the start of the new process of this event, Activity Manager will notify the new process to do the real activity startup process, which create the Activity class according to the manifest then call OnCreate etc.
There is a few answer here that is totally wrong which get a lot of votes, hope a moderate etc can check this.
Look at the stack frame it starts from the main().

Java Applet runs without a main method?

I was running a Java class that extends Applet implements Runnable and apparently the program can run, but there is no main method. I thought Java applications needs the main method as its entry point?
Java Applets have an init method instead of main.
It's:
public void init() {... }
Yes, but applets aren't applications. There is a main method in the applet runner (assuming it's implemented in Java; it need not be) but the applet doesn't work that way; it gets loaded/instantiated from a file and then it proceeds along its lifecycle through initialization, starting, operating, stopping, and finally being destroyed. The code that sends it through these states is hidden from the applet's view; it just knows its in an environment that can run applets.
Applets differ from stand-alone Java applications in that they do not need to implement a main method.
Life Cycle of an Applet
Copied from google results:
Applets are standalone programs which require a third party tool for its execution that is either it is java enabled web browser or applet runner. So it doesn't have main(). It is
possible to run a program without main.
Possible duplicate of:
Why do applets not need a main()?

Why is a windowOpened event not fired/captured when my Eclipse plug-in starts?

I am writing an Eclipse plug-in and one of the classes implements IWindowListener. As a result, I have a few methods that must be in my class including windowOpened(IWorkbenchWindow window). My understanding of the windowOpened method is that it should be called when the Eclipse Application is launched and the plug-in starts, however I have included some log statements in this method and it never gets called.
Does anyone know why this is happening? Has anyone experienced a similar issue?
It should be noted that the other IWindowListener methods seem to work fine. For instance, the windowClosed method is properly called when I exit the Eclipse Application that the plug-in is running in.
Probably because by the time your IWindowListener is registered, the window is already open. Remember that Eclipse plug-ins are started lazily; unless you've taken steps to have your plug-in start up early, it won't get started until the first time one of its classes gets loaded.
You can access eclipse startup by using extension point called "org.eclipse.ui.startup", with this you need to implement interface IStartup and you can do any startup processes there. This is really done before the actually UI is even loaded.
PlatformUI.getWorkbench().getActiveWorkbenchWindow() will return null! You can get pass that by doing Display.asyncExec(Runnable) what will wait until the things are started
Please notice that this will not load your eclipse plug-in, that IStartup class is just executed at the startup. Your own plugin should really be loaded when it is needed first time, not before that. Because there is no need for it to be started until it is really required.
Also a proper place to do some plugins startup stuff is at Activator's start() function. This is called when your plugin is really loaded first time.

Categories