I'm taking a CS Data Structures course, and I want to try and work with VS Code instead of the current editor that I'm using (BlueJ). However, my work is evaluated based on whether it can satisfy a certain set of tests presented by a compiled tester file (a .class file that I can use to run/check my work), something that VS Code doesn't seem to particularly like.
This tester is what contains the program's main() method, so I either need to use BlueJ (which already supports running compiled classes) or run the file from the command line (something that I know how to do, but have found somewhat tedious) in order to run the method. Is there a way that I could configure a VS Code Java debugger to execute the main() method located within my compiled tester file?
A note: These tester files do not come with editable .java counterparts; if we were able to see what the tester checks for, that would ruin the point of the tester!
Not exactly what you want, But:
For tedious commands, you could set up an alias in your $HOME/.bash_aliases file.
Bash Aliases .
i.e one i aliased earlier :
alias ds="java -cp $HOME/javaWorkScripts/jspDatabaseApp/bin/ FormatTabContents $HOME/VSCODE\ Research/SURFACE-TIDE-JSP-DATABASE-APP-22-DEC-2018.txt "
From now on, you could just type ds in terminal to run the command.
You can decompile and debug the class in IntelliJ easily. Then set break points on main method and check it.
You can decompile the class in VS code easily but I doubt you will be able to debug the .class file in VS Code.
Related
I'm trying to make a java program which executes java files and gives output in the text field. I've used Runtime class to compile the .java file .So how do I get the output from that newly made class file.
Runtime.getRuntime().exec("javac Y://CodeSave.java");
Runtime.getRuntime().exec("java Y://CodeSave.class>output.txt");
In the general case: exec returns a Process instance which has accessors (getOutputStream, etc.) for the I/O streams. You read from / write to those streams.
But: In your code you've used >output.txt. That's a shell feature. If you want to do it that way, you need to spawn a shell, not the java tool directly, and have the shell execute that command line. (A search for spawning/execing a shell should find you lots of examples.)
Using Runtime.exec is definitely not the right way to do it, for various reasons. Examples are that both java and javac rely on environment variables which you can't pass that way.
First of all, I'd ask myself if I really needed to do this. Compiling and executing dynamically created code is a huge security risk.
But if you're sure you need to do it, here's what I'd do.
Move your sources to a dedicated temporary folder
Use the ToolProvider api to compile your sources
Use a dynamic throwaway ClassLoader (ByteBuddy may help you there) with a SecurityManager to load and execute your code from within your application
Is there any way to run a Java jar file in R? I want one of the outputs of a .jar be used in R.
You can use system to run an operating system command from R.
To run a java jar on a well-configured system, this should work:
system("java -jar /path/to/my.jar")
You can add other parameters, for example maybe the Java code takes input from a file which you write with R and pass the filename. Then output from the Java code could be written to files and then read from R. Without knowing what the Java code does we can't be more specific.
It is possible to directly interface with Java code but that requires full knowledge of the internals of the jar so you know what functions to call with what parameters. This is usually referred to as the "API" for that Java.
Otherwise, write a file, call system, read a file, is sometimes the simplest way to run code in other languages.
Java's .jar can only be run by java; so what you need is a way to run an external command from R. The command will be java, with arguments -jar and your.jar.
As far as I can tell, you need to use system function, something along the lines of
javaOutput <- system("/usr/local/bin/java -jar your.jar", intern = TRUE)
(note I have not tested that, so please do test)
I'm grading an assignment in Java. Students are asked to implement a Five-In-A-Row (like Tic-Tac-Toe, or two-player Pente) interface which is used by a GUI .java file. These files (interface and GUI) are given to the students in a file called lab2.jar (where they're in cs251/lab2/ under the names GomokuModel and GomokuGUI, respectively), which the students must add to their classpaths. When the project is finished, students are requested to turn in a .java file called Gomoku.java.
One student turned in a .jar, but the command
java -jar Gomoku.jar
responds with
no main manifest attribute, in Gomoku.jar
I figure the student may have forgotten / not known to make a manifest file. I unzip the student's jar and find only .class files. I try to make my own jar from these files:
According to specs, the main must be in Gomoku.java, whose class is Gomoku.class. So I make a manifest.txt file that looks like
Main-Class: Gomoku
Class-Path: lab2.jar
And try to make a .jar out of it using the command
jar cfm myJar.jar manifest.txt *.class lab2.jar
But when I run this using the command
java -jar myJar.jar
I get the following error:
0Exception in thread "main" java.lang.IllegalAccessError: tried to access method cs251.lab2.GomokuGUI.<init>(Lcs251/lab2/GomokuModel;)V from class Gomoku
at Gomoku.main(Gomoku.java:47)
This particular error is giving me trouble. I've never seen anything like it, and my research on the web doesn't turn up anything. Because the error says it's coming from GomokuGUI, which is one of the lab2.jar files, I think the error's on my end. My questions are:
Can I make an executable .jar when I know and have
What goes in the classpath
Where the main should be
A set of relevant class files
If the answer to (1) is yes: Am I going about it in the right way? I have a feeling I'm missing a recompile step somewhere.
In this particular case, I may ask the student to resubmit. And I will download the .jar's I see submitted before due date to make sure they are runnable. But for knowledge's sake (I myself have made .jar files that have had only .class in them and no manifest), is there a way to salvage a working file like the one described above?
From the JRE javadoc:
public class IllegalAccessError
extends IncompatibleClassChangeError
Thrown if an application attempts to access or modify a field, or to
call a method that it does not have access to.
You're getting
0Exception in thread "main" java.lang.IllegalAccessError: tried to access method
cs251.lab2.GomokuGUI.<init>(Lcs251/lab2/GomokuModel;)V from class Gomoku
at Gomoku.main(Gomoku.java:47)
The method it's complaining about is named <init>. That's what Java calls constructors, internally. It's saying that Gomoku.main() tried to issue new GomokuGUI(model) where model is expected to be an instance of GomokuModel, but that this constructor was not accessible. The fact that Gomoku.main() is in a different package from GomokuGUI means the constructor would have to be public for that to work.
You can check that via reflection -- I believe Eclipse can do that for you, actually -- but that's almost certainly what's going on.
So either the student turned in broken code, or you broke it during your attempts to force-fit it into convenience-executable jarfile format. Which was wasted effort in any case, since you can't grade the assignment based on object code and you're going to have to go back and ask for source code anyway.
If you really want to try running the jarfile the student submitted: Go back to the original unmodified jarfile and try just running 'java Gomoku -classpath myJar.jar' where myJar.jar is what the student turned in. If that doesn't work, try 'java Lcs251.lab2.Gomoku -classpath myJar.jar', which is probably the package they intended to put it into given the error message you're getting. If neither of those runs, ask the student what command line they've been using to run it and try that. If THAT doesn't work, then it's time to investigate why.
The whole executable-jar question is a red herring and a waste of time until you know the code actually runs and what the entry point actually is.
In Unix (or Linux), if I want to run a shell script, I can start the file with #!/bin/sh. With awk, I start the executable file with #!/usr/bin/awk -f and it treats the rest of the file as the program.
How do I do that with a Java program? I tried copying the simple.class to simple, putting #!/export/appl/Mail/java/bin/java at the top and making the file executable, but I get:
69> ./simple
Error: Could not find or load main class ..simple
I know this can be done with an executable shell script, or a C program that execs the java interpreter. Every other interpreter on Unix can be called with a #! load card, surely there's a way to do it with Java.
The most usual way is to have a wrapper for the Java. A shell script that executes the "java -jar yourJar.jar" or equivalent. And then you bundle the shell script and the windows equivalent bat file with your product.
Another option is to have a native launcher. For example you can see the Eclipse project which has gone that way. You download Eclipse and you have a native executable to run. The native executable will launch your Java program.
One more option is to compile Java into native code. For example you can use this commercial tool called Excelsior JET ( http://www.excelsior-usa.com/jet.html ).
The Java class file format doesn't allow text before the header, that's why the Java runtime no longer accepts the .class file after your modification.
On Linux you can use binfmt_misc to support additional executable formats, including .class files. It's basically a way to tell the Linux kernel how to detect executable formats and how to execute them.
This Archilinux Wiki article explains in more detail how to get this effect.
You cannot do it with a Java program. Firstly, the Java program needs to be compiled before execution. Secondly, even if compilation wasn't required, the hash sign is not a comment in Java, so that would be a syntax error.
I've never heard the term "load card". What you have is an "interpreter directive" designated by a shebang. This merely designates which interpreter the shell should invoke on a given script.
As for why C programs can be run directly in the shell, executables recognized by the operating system are passed to the loader. A Java class isn't an executable, at least to the OS anyway. So the shell must know which interpreter to pass control to.
But as you've noticed, the shebang doesn't work. The reason is that the class file is in a specific binary format that the JVM expects. Editing this file will break convention and lead to an error. Therefore, there is no way to do what you've asked.
However, you can create a "shortcut" to the program you want to run by creating an alias or perhaps writing a one-line Shell script to wrap the java command you need. This is the common practice as I understand it.
The other answers explain why you can't do what you are trying to do. However, if your shell is zsh, you can create a suffix alias. For example, to execute .jar files using java:
alias -s .jar="/usr/bin/java -jar"
Then, to execute blarg.jar, you just type ./blarg.jar. Of course, you must chmod +x your .jar file first.
Apart from the wrapper script and binfmt_misc solutions suggested by others, I'd like to suggest a potential solution which doesn't directly answer your question but maybe it solves your actual problem.
Since Scala does have an interpreter that can run code without you having to compile it first, and this code can reference any Java code, if your goal can be summed up as "using Java as a shell scripting language", you could use a .scala file as your starter script (which can include the shebang to be run with scala) from which you can call all your Java classes. This isn't any simpler tha having a bash-based starter script, but it's a good starting point to gradually move to scripting in Scala instead of Java in which case you can get rid of the need to compile to .class file in the first place.
The reason this doesn't work is that Java isn't really an interpreted language, it's partially compiled, partially interpreted.
The .java source code that you'd put the hashbang directive in needs to be compiled to a .class file before the java interpreter can run it. Comments are stripped out by the compiler, so there's no way to push a comment from the .java into the .class file. The .class file is "compiled" output in a specific format, so adding a hashbang directive to the top of it would break the format.
Java isn't really meant to be a scripting language - but some JVM languages are. For example Groovy supports hashbang and so does Clojure.
I'm using SciTE to write a small amount of Java at the moment. Only stuff to learn the language basics etc. At the moment I have a base directory, Java, a sub directory, practice, which has 2 subdirectories, running & testing. When I use the "build" command in SciTE I've managed to set that up to work. But what I cannot get working is the Java\practice\testing\ModelTester class (practice.testing package) to run. I get a NoClassDefFoundException and a wrong name message.
I know that the problem is the I need to run:
java practice.testing.ModelTester
but how do I get this into the command.go.*.java section of the SciTEDirectory.properties (in the Java directory). Obviously I would like something to put in command.go.*.java that can apply to any and every Java file I might run in a package.