Running JavaFX app without main method - java

This material says on page 10 that it is possible to run a JavaFX app without writing main. I suppose there is some predefined main inside jfxrt.jar which looks for a class extending Application and runs it.
Is that so? How to do that?

I suppose there is some predefined main inside jfxrt.jar which looks for a class extending Application and runs it.
This isn't really what's meant by that comment, and isn't how it works. All it is saying is that the "main class" doesn't need to define a main(String[] args) method if it is a subclass of javafx.application.Application. From the Oracle tools documentation for java:
The java command can be used to launch a JavaFX application by loading a class that either has a main() method or that extends the javafx.application.Application. In the latter case, the launcher constructs an instance of the Application class, calls its init() method, and then calls the start(javafx.stage.Stage) method.
(My emphasis)
So if the class specified on the command line is a subclass of Application, this behavior is simply baked into the JVM executable. Note that you still have to specify the class that is to be run; it just doesn't need a main method if it is an Application subclass. (The JVM is not scanning the classpath for candidate classes to run, as you seem to be describing in the question.)
The class to be run can be specified on the command line (java com.mycompany.MyApp) or can be specified in a jar file manifest in the usual way.
This was added in JDK 8, iirc.

Related

Why Eclipse Ide and Tool Suite won't compile/run my class, just that class which is the main, or a previous one

yesterday i was trying to run a simple Java class, with a simple method void to print something, when i want to run that class i got something weird... either Eclipse IDE run a different class (a previous one) or don't run at all, just asking for a main class from that package... but why? I mean, if i create a new Maven project, or a new Class, i expect to run that class, but if i want to Run as -> and searching for Java Application, doesn't apper. Anytime i want to run something, either i neet to run that main class from that particular project/package created or Eclipse running a whole different class from a few days ago when all was good. The same thing i occur in tool Suite...
If you need some photos of configuration or something, feel free to ask, right now i don't know what to do...
Edit: I created a Maven project with a new Class, TestVoidClass with a void method that prints: System.out.println("Inside TestVoidClass");
So now i have two classes in my MavenProject, App class with main method who works fine and i can run that hello world print, and TestVoidClass, who doesn't work, doesn't appear to run as Java Application... bellow are some photos
First photo showing that it's running a previous class:
Second photo showing i can't find that Run as Java application:
Working with default App maven project main class:
make sure the class you want to run contains a main-Method. That is:
public static void main(String[] args) {...}
If a class doesn't contain this method, it can't be run. In your main-Method, you can call your Sysout() function.
If you open a class containing a main-Method, Eclipse will automatically run it when you click Launch.

Instrumenting Android apps with Soot using a helper class

I am instrumenting Android applications using a helper class following the example for Java instrumentation in http://www.sable.mcgill.ca/soot/tutorial/profiler2/profiler2.html.
In my BodyTransformer, I have a static block to load MyCounter class
counterClass = Scene.v().loadClassAndSupport("MyCounter");
Since Soot.Main.main(args) that processes my args (in which I provide -android-jars) is not executed while it is loading MyCounter, Soot cannot find my android jar and gives the error:
Caused by: java.lang.RuntimeException: You are analyzing an Android application but did not define android.jar. Options -android-jars or -force-android-jar should be used.
at soot.Scene.defaultClassPath(Scene.java:455)
at soot.Scene.getSootClassPath(Scene.java:224)
at soot.SootResolver.<init>(SootResolver.java:81)
at soot.Singletons.soot_SootResolver(Singletons.java:802)
at soot.SootResolver.v(SootResolver.java:91)
at soot.Scene.loadClass(Scene.java:667)
at soot.Scene.loadClassAndSupport(Scene.java:653)
at MyBodyTransformer.<clinit>(MyBodyTransformer.java:26)
... 1 more
As a solution, I provided my command line arguments (android jars, soot classpath, prepend classpath and process directory) in my main class, before creating my BodyTransformer. Now, it works.
I would like to ask whether there is a more proper way to solve this problem.
loadClassAndSupport is nor sufficicient. Here is what you should do. In your analysis' main method, before you call Soot's main method add the following:
Scene.v().addBasicClass("MyCounter");
Then within your analysis simply use Scene.v().getSootClass("MyCounter").

OSGi service: java.lang.UnsatisfiedLinkError calling DLL -- NO error when DLL called as unit test

A Java class made for video coding loads a DLL including C++ code
Unpacking debugging symbols for VideoSource.dll to \path
Checking for VideoSource.pdb...
Checking for videosource.pdb...
and then tries to instantiate a native (C++) class from that DLL:
// VideoSource() is implemented in C++ and wrapped with JNI,
// wrapper files were generated with SWIG
_videoProvider = new generated.VideoSource();
That works when the Java class is executed as a JUnit test (video data is extracted).
Same thing does not work when I launch the Java class as an OSGi service.
Essentially, the same code is executed. The DLL is still loaded successfully but the instantiation of the native (C++) class shown above now throws an exception:
java.lang.UnsatisfiedLinkError: generated.VideoSourceSWIGJNI.new_VideoSource()J
What is different when I launch the Java class as an OSGi service instead of executing it as a JUnit test? What can I do to make it work?
BACKGROUND
generated.VideoSource() is
public VideoSource() {
this(VideoSourceSWIGJNI.new_VideoSource(), true);
}
VideoSourceSWIGJNI.new_VideoSource() is
public final static native long new_VideoSource();
C++ implementation is
VideoSource::VideoSource() {
// init frame count
m_frame_cnt = 0;
[..]
}
Thanks, Puce, for pushing me a bit. After asking "would I have to try anything at all"? I got the answer relative quickly:
In order to resume sources (1, 2, 3, 4) with my own words:
When native code, e.g. .so or .dll libraries, shall be used in an OSGi bundle, corresponding libraries have to be declared in the bundle's manifest.
The manifest file may either be edited explicitely, as stated in mentioned sources, or implicitely via an appropriate plugin, e.g. apache felix, when using maven. Used plugin is configured in the POM file and will modify the manifest automatically.

How to run the main method of an Android Activity class?

I'd would like to examine a private method of an Android Activity by executing it within the Activity's public static void main(String[] args) method which I created.
I use Eclipse ADT and my naive approach of running the Activity as a Java application resulted in:
A fatal error has been detected by the Java Runtime Environment:
Internal Error (classFileParser.cpp:3174), pid=2936, tid=2980
Error: ShouldNotReachHere()
So I looked at the Run Configuration and found out that Android 3.1 is the sole entry in the Bootstrap Entries section of Classpath. I managed to configure the Build Path of the project so that the JRE is in the Bootstrap Entries too. Then I removed the Android 3.1 entry and added android.jar to User Entries.
The result of executing the Run Configuration is a RuntimeException:
Exception in thread "main" java.lang.RuntimeException: Stub!
at android.content.Context.(Context.java:4)
An alternative of executing some tests would be to fire up a JUnit test. But in the case of a private method this is cumbersome.
Is there a way to successfully run the main method of an Android Activity class?
There is another option for the problem at hand, if the private method - which should be examined through the execution of a main method - can be extracted to another class. This of course means that the method suddenly became at least protected.
But if the method is definded within a class that does not derive from android.app.Activity a main method can be defined. You only have to adjust the Run Configuration in Eclipse.
Run the class with Run as Java Application. This generates a new Run Configuration named like the class
Edit the newly creaded Run Configuration
Delete the Android library from Bootstrap Entries in the Classpath tab
Add JRE 6 or so to the build path of the project
Add this JRE to the Bootstrap Entries in the Classpath tab
Add android.jar, which resides in the platforms directory of the Android SDK in User Entries in the Classpath tab
Activity is very important from Android's point of view, Activity's lifecycle are collections of few methods which are handled by OS through out the activities' life.
public void onCreate(Bundle savedBunldeInstance)
is called as soon as the App is launched creating the activity. This is the entry point of an application in android. You must have the emulator or physical device for running Android app, Here the file is compiled 2 times, once by java compiler then by dalvik compiler.
DVM (Dalvik Virtual Machine) is located on the Android device (EMULATOR OR PHYSICAL), this is the reason why we need emulator or physical device to run it..and onCreate is the entry point for it.
On your request I am editing this post with an additional piece of information. The lines below are abstracted from http://developer.android.com/
Android applications don't have a single entry point.
(there's no main() function, for example).
for further details click this :
http://developer.android.com/guide/topics/fundamentals.html
The main method isn't the entry point in Android like in Java. You wanna override the
public void onCreate(Bundle savedBunldeInstance) method.

java.lang.Class#getAnnotation() returns null when called in eclipse plugin

I am writing an eclipse plugin to support the Frege programming language.
I use the IMP meta tooling platform and Eclipse Indigo (3.7). The run time environment is Java 1.7.
The plugin uses the same code as the batch compiler for token parsing, syntax analysis, etc. However, I noticed differing behavior when run from the eclipse plugin and traced it down to the following method that reads a class file of a previously compiled module to get meta-information which is stored there in form of java annotations:
public static MD.Operator[] getOperators(ClassLoader loader, String pack)
throws ClassNotFoundException {
Class<?> cl = null;
cl = loader.loadClass(pack);
MD.FregePackage os = cl.getAnnotation(MD.FregePackage.class);
if (os == null) return null; // <-- no annotation present
return os.ops();
}
Note that the code creates its own instance of an URLClassLoader, which is passed as argument. If I do not set the class path correctly, the getOperators method correctly throws a ClassNotFoundException, therefore I think I can be sure that it loads the class.
A trace message tells me that the class loader is built with the following path (which is just the classpath by default):
mkClassLoader:[C:\opt\eclipse\plugins\org.eclipse.equinox.launcher_1.2.0.v20110502.jar, X:\dev\frege\build]
Because a class file not created by the frege compiler cannot normally have the MD.FregePackage annotation this usually indicates that the user tried to import a plain java class, and indeed I get the following message in the plugin:
X:/dev/runtime-EclipseApplication/TestJFrege/src/Neu.fr:1: `frege.prelude.Base` is not a frege package
Yet, from the command line I can compile this just fine. I included this here as proof that the annotations in question can indeed be loaded from the same location:
X:\dev\frege>java -cp ./build frege.compiler.Main X:/dev/runtimeEclipseApplication/TestJFrege/src/Neu.fr
mkClassLoader: [./build]
running: javac -cp ./build -d . -encoding UTF-8 ./Neu.java
Resuming the facts:
The code that is supposed to load the annotations works fine when the compiler is invoked via command line interface.
The code that is supposed to load the annotations does not know whether it is invoked from the plugin or the command line. In fact, the plugin didn't even exist until last week, while the command line interface used to work fine for months.
The annotations have, of course, RetentionPolicy.RUNTIME otherwise the command line compilation would not recognize them either. But it proovably does.
So the only conclusion I can draw is that Class.getAnnotation() somehow is not working correctly. This is very unfortunate, as this effectively destroys basic functionality I need for the module system.
If this matters anyhow: the Frege compiler code the plugin uses is itself written in Frege and the frege.prelude.Base class mentioned above is a basic library that is needed by every module, hence it must already have been loaded on activation of the plugin, though of course with a different class loader.
Does anybody have similar experiences? Is it possible to solve this and how? Any suggestions how to circumvent this are welcome.
Was the MD.FregePackage class loaded by the classloader used in your method? Possibly try loading that one first, since two classes aren't equal() if they were loaded by different class loaders. That could explain why it isn't being found.

Categories

Resources