Run javac compiled groovy code using java? - java

I have a simple groovy file as follows:
class test2 {
public static void main(String[] args) {
println("In groovy!!");
}
}
My gradle task is compiling this into a test2 class file
How do I run this file from prompt ?
java test2 (from the location of the test2.class file)
causes a : Error: Could not find or load main class test2.class
I assuming I need to add asm and groovy to the class path. However:
java -cp "groovy-all-2.3.6.jar;asm-all-3.3.1.jar" test2
also doesn't work (files are in correct locations).

I know this may be a bit late for the OP but nevertheless:
Given that your groovy main exists, the error message:
Error: Could not find or load main class YOUR_MAINCLASS_HERE
from the java command while executing a groovy main (of a compiled groovy file which produced classes) means basically that your groovy jar is not in the classpath.
Longer Answer:
Lets see why that is for a simple hello world example. I have a file called main.groovy with the following content:
class Main {
static void main(String[] args){
println('hello world')
}
}
Put this somewhere in your filesystem. Open a command prompt in the same directory and ensure that groovy and java is accessable though the PATH.
In the command prompt, compile the file with groovyc, so just type in:
groovyc main.groovy
This will produce a file called Main.class (with uppercase M because of the class name).
Ok now we have the appropriate test setup. If you now try to run the file just with java command:
java Main
you will get the error message:
Error: Could not find or load main class Main
This is a bit unexpected, because one can think that we just can invoke the main in our Main.class without linking the groovy library, so we would expect an exception like ClassNotFoundException.
In contrast, try again with groovy in your classpath. I will refer to the directory of your groovy installation as GROOVY_HOME. To run the hello world Main class finally, we can type in:
java -cp ".:/$GROOVY_HOME/lib/*" Main
which produces the expected output on unix-like systems (on windows you need to replace the colon with a semicolon and the variable access would be like %GROOVY_HOME%).
The reason is quite simple: Groovy produces for groovy main methods not the same signature as required by the java specification. Therefore, you can only invoke a groovy main with groovy on the CLASSPATH - what makes totally sense!
You can check this for yourself. Try now the command:
javap Main.class
This will give you a quick analysis of the bytecode and the present interfaces of the class "Main.class". All along you will see something similar to this output:
Compiled from "main.groovy"
public class Main implements groovy.lang.GroovyObject {
public static transient boolean __$stMC;
public Main();
public static void main(java.lang.String...);
protected groovy.lang.MetaClass $getStaticMetaClass();
public groovy.lang.MetaClass getMetaClass();
public void setMetaClass(groovy.lang.MetaClass);
public java.lang.Object invokeMethod(java.lang.String, java.lang.Object);
public java.lang.Object getProperty(java.lang.String);
public void setProperty(java.lang.String, java.lang.Object);
}
Of interest is line 5:
public static void main(java.lang.String...);
This seems quite similar to a normal java main, but with one difference: groovyc used an java.lang.String ellipsis (as stated by the three dots) and not and java.lang.String[].
So this could be the reason. I'm not so sure, because normally java will give you an appropriate error output if it can find the class but not the method signature. For example, try:
java java.lang.Integer
which has clearly not a main method. Java sees that correctly:
Error: Main method not found in class java.lang.Integer, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
I'm also not sure, what groovy does during class loading for understanding this kind of main signature (or lets says this kind of bytecode), but if you compare that with a normal java hello world javap output, you get
public class JMain {
public JMain();
public static void main(java.lang.String[]);
}
which has a different and the normal java main signature.
Maybe someone from the pivotal groovy team can clarify.
I hope this will give you a hint.

The test2.class needs to be on your CLASSPATH. For example, if it is at /Users/you/classes/test2.class then /Users/you/classes/ needs to be on your CLASSPATH.
Since you are building with Gradle, you could also just let Gradle sort all of that out for you using JavaExec. See http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.JavaExec.html for more info. A simple example in your build.gradle might be something like this:
task myTask(type: JavaExec, dependsOn: 'classes') {
main = 'test2'
classpath = sourceSets.main.runtimeClasspath
}
I hope that helps.

Related

How to run a java .class file that extends a Class which is in another directory?

I first met this problem in my Ideas, I wrote a Class that extends javax.servlet.http.HttpServlet, My Ideas throws an error message reads Error: Could not find or load main class com.bjpowernode.OneServlet, here is the image:
enter image description here
It can be seen that Idea didn't show the red wavy line, that shows my codes are fine. I found a solution to this problem from enter link description here, I changed the scope from provided to compile:
enter image description here
But I actually want to know why and how it works? I compared the difference of Idea compilation instructions under different scope setting,I found that when Idea uses java command to run the .Class, the parameter -classpath of the command of the compile scope has two more paths:
D:\apache-tomcat-8.0.50\lib\jsp-api.jar;D:\apache-tomcat-8.0.50\lib\servlet-api.jar
That's to say, Idea didn't consider external library paths when run .class under the provided scope, and the super Class HttpServlet is from servlet-api.jar package. Why?
To simplify the problem, I created two different classes under two different paths and packages: Class Base and Class Sub, and Sub extends Base.
The codes of the Base is here:
package base;
public class Base{
public static void main(String[] args) {
}
}
The codes of the Sub is here:
package sub;
import base.Base;
public class Sub extends Base{
public static void main(String[] args) {
System.out.println("In Sub");
}
}
The path of Base is ./path1/base/Base.java and the path of Sub is ./path2/sub/Sub.java.
I compiled them using these two commands:
javac ./path1/base/Base.java -d ./path1
javac ./path2/sub/Sub.java -d ./path2 -cp "./path1;./path2"
And compiled successfully. But when I run sub.Sub using the command below:
java sub.Sub -cp "./path1;./path2"
And I got the same error:
Error: Could not find or load main class sub.Sub
Ive tried multiple variations of this, but none of them seem to work. Any ideas? Although I solved the problem of idea reporting errors, I still could not understand the principle behind? I hope this question can help me to figure it out. My jdk version is 1.8. Thanks in advance.

`java CloseSignals.class` on the command-line doesn't work

I compiled my only class, CloseSignals.java, producing CloseSignals.class. When I try to run it using java CloseSignals.class, it says "Could not find or load main class CloseSignals.class". I have looked this problem up and it seems like this problem should only occur if i'm trying to start the program from some class in a package. This isn't in a package, I'm just trying to compile this simple program.
What could it be?
You have to have method public static void main(String[] args) defined in your class in order to be able to run it - this is where your program starts:
public class CloseSignals {
public static void main(String[] args) {
// your code here...
}
}
If you have the main method in that class, you can compile it like this:
javac CloseSignals.java
And then run it using the following command:
java CloseSignals
Note you run it using the class name, not the actual file name.
When you compile your code use '.java' extension like
javac YourClass.java
but when you run it Not use '.class' extension
Use like
java YourClass

How to run a Java HelloWorld program?

I have run into an error. I think my code is right. here it is... please tell me what I have done wrong!!!
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World");
}
}
The error I keep getting is...
Error: Could not find or load main class javatest.java
The file name of the Java Class file must be the same one as your Class.
Class: public class HelloWorld {}
File: HelloWorld.java
The code seems right. Perhaps the issue in how you run it.
The convention is to keep the file name and the public class name as the same.
When compiling, use javac <filename>.java. Then to run simply use java <classname>. So, you would use java HelloWorld, HelloWorld being the class that contains the main method.

Why can't we define main function in static inner classes?

I have the following simple code
public class Tester {
static class TesterChild {
public static void main(String args[]) {
System.out.println("Test");
}
}
}
It compiles fine. But when I run it I get the following Error
[aniket#localhost src]$ java Tester
Error: Could not find or load main class Tester
Question is why can't we define our main method in static inner class?
Update1 :
As specified in the answers/comments I have change the code to following
public class Tester {
public static class TesterChild {
public static void main(String args[]) {
System.out.println("Test");
}
}
}
I compiled it and it made two class files Tester.class and Tester$TesterChild.class. But still i am getting error
[aniket#localhost Desktop]$ java Tester$TesterChild
Error: Could not find or load main class Test
Update 2:
Ok now I included current directory in the classpath and executed still getting error
[aniket#localhost Desktop]$ java -cp . Tester$TesterChild
Error: Main method not found in class Tester, please define the main method as:
public static void main(String[] args
It can be run as main but you are not using the right class. Your main class is not Tester but Tester.TesterChild.
In Eclipse it will run without any setup but from the command line you have to use the java 'yourpackage.Tester$TesterChild' syntax as others mentioned above.
You need to wrap the name of your class in ''s because on linux/unix the shell might think that $TesterChild is a variable. If you try it out in the prompt you will get something like this if you omit the ''s:
Error: Could not find or load main class Tester
If you need to explicitly set the classpath you can use the -cp or the -classpath option or you can set it from the commandline: set CLASSPATH=/somedir
Since you have defined main() method in inner class.
Run the inner class to get main() to be executed.
use command line java Tester$TesterChild.
update
I think you are placing java file in some package.If then use this command line.
java -cp . yourPackageName.Tester$TesterChild
For example I have placed file in a package named test.Then my command is like this
java -cp . test.Tester$TesterChild
Beware that the dollar sign has special meaning to most shells. I.e. if you write
java -cp . Tester$TesterChild your shell might replace $TesterChild with the contents of an environment variable with that name or silently replace it with nothing if it doesn’t exist. Try java -cp . 'Tester$TesterChild' or java -cp . Tester\$TesterChild

Is Java not installed correctly? Exception in thread "main" java.lang.NoSuchMethodError

Recently when I write any code and compile it, then try to run it I get this exception:
Exception in thread "main" java.lang.NoSuchMethodError
At first I thought there is something wrong in my code, but I couldn't find anything wrong with it. When trying to run a HelloWorld example that had worked before, if works, but if I copy the exact same code into a file HelloWorld2 I get this exception again.
The code is identical but when I used javap to decompile both class files I found a difference. In HelloWorld (the original file)
"public static void main(java.lang.String[])";
and in HelloWorld2 (the new one)
"public static void main(String[])";
without java.lang..
I recompiled the old HelloWorld with javac and now when I try to run it it doesn't work and I get the same exception. None of my old code now works if I recompile it.
I've searched everywhere but can't find a solution to this problem - any idea what is going on here?
You may get this if you have your own class called String (without a package) in your classpath. It sounds like that's what happened. Here's a way to try to reproduce this - compile it and run it, and see if it looks the same:
class String {}
public class Test {
public static void main(String[] args) {
}
}
Once you've got the compiled String.class file in your file system in an awkward place, that will be used by default even if you only compile the Test class above...
Basically, see if you can find a file called String.class somewhere.

Categories

Resources