I found this question, and this other, so intriguing that it begs several questions, at least for me:
Rather open-ended question, but where is jshell confined to? Obviously, GUI apps aren't in the domain for jshell solutions, or IDE replacement:
Out of scope are graphical interfaces and debugger support. The JShell
API is intended to allow JShell functionality in IDEs and other tools,
but the jshell tool is not intended to be an IDE.
Bonus points for Venn diagrams or other visuals.
Certainly, snippets should be limited in size. I'm more asking what sort of problems cannot be solved with snippets.
see also:
https://openjdk.java.net/jeps/222
https://openjdk.java.net/jeps/330
Answering the updated question
All problems can be solved with snippets (and with a sufficiently complicated shell script, too). But JShell is best used to debug and learn java - a full-fledged program is much more flexible for all other use-cases.
JShell, .jsh and java MyClass.java
JShell is an interactive shell for trying out java code. Essentially, it is a REPL for Java.
Since JShell is all about you typing in code snippets, which it then evaluates, and it often makes sense to put those snippets in a file instead of writing them several times, JShell supports .jsh scripts, which contain collections of snippets to be interpreted by JShell. In this sense, this is similar to bash accepting .sh files or command.com accepting .bat files -- typing them line by line is equivalent to importing them.
Single-source java-file execution is a very different beast. It is sugar that replaces, from JDK 11 onwards,
java MyClass.java arg1 arg2 arg3
by your local scripting equivalent of writing
TMPDIR=$(mktemp -d)
javac -d $TMPDIR MyClass.java
java -cp $TMPDIR MyClass arg1 arg2 arg3
rm -rf $TMPDIR
This allows single-source files to be quickly executed from the command line with a single command, and without leaving their compiled classes all over the place (no actual temporary directory needs to be created, as java can store those classes in memory). Since they already had 3 other execution modes in java (for classes, jar-files and modules), it is no great stretch to add this as a fourth one.
Since OP wanted a picture:
Java as a scripting language
Now that the distinction is clear (.jsh is for use with JShell, single-source java executables are only for, you guessed it, single-source java executables), what about using Java as a scripting language?
You have always had the option to write a launcher; for example,
#!/bin/bash
java -jar MyApp.jar
has worked for ages. It was technically possible to name a class directly, but not too useful, as jar files are far more handy when distributing binaries -- for one thing, they avoid mirroring the package structure as a bunch of folders. Having a launcher script as separate from the actual java code was, however, still somewhat unfriendly: you now need to keep both together, or at least have the launcher be able to locate the actual .jar to launch.
Now, they have also introduced the following shortcut: regardless of file name or extension, you can distribute your java source with a "shebang prefix" as follows:
#!/path/to/java --source 11
<source of MyClass.java>
mark it as executable, and launch it from the command-line just as you can launch any other executable. For example, copy and paste this into a helloworld file (and fix the jdk location before attempting to run it):
#!/opt/jdk-11.0.1/bin/java --source 11
public class Test {
public static void main(String ... args) {
System.out.println("Hello " + (args.length == 0 ? "world!" : args[0]));
}
}
After marking it as executable, you can launch it directly with
$ ./helloworld
Hello world!
and it even takes its arguments right:
$ ./helloworld Bob!
Hello bob!
For small programs, and provided you do not need to go outside of the JDK to pull in additional libraries, it will now be vastly easier to distribute java code for command-line use.
Java will still not be a "scripting language" (it will never compete with, say, python), but
it has a very nice REPL loop
you can execute short programs a lot easier
Well, of course, its confined to a bring a normal REPL utility in terms of scoping what an IDE and graphical user interfaces could provide. I would talk of more about its capabilities as compared to single source code programs. The features that keeps it apart still from single source code programs:
a history with editing
tab-completion
automatic addition of needed terminal semicolons and
configurable predefined imports and definitions
As mentioned in the alternatives to Single-File Source-Code Programs JEP as well:
We could delegate the task of "one-off runs" to the jshell tool. While
this may at first seem obvious, this was an explicit non-goal in the
design of jshell.
The jshell tool was designed to be an interactive
shell, and many design decisions were made in favor of providing a
better interactive experience.
Burdening it with the additional
constraints of being the batch runner would detract from the
interactive experience.
!!! Limitations and behavior!!!
On the other hands, few limitations(assumed functionalities) that one would mostly find while performing a hands-on using JShell rather than simply reading the docs would be :
use of final variables final variables are not functioning well in jshell
of course Debugging with JShell
integration of jshell with IDEs Java 11 JShell inside Intellij IDEA
disabling history Disable JShell history
redeclared variables should be reset In jshell-11, why does a redeclared reference variable that resets to null still have a type?
create module using jshell Create Module in JShell in Java 9
importing private package classes Importing Package-Private Classes to JShell
scope of objects Access to "parent scope" in JShell
clear jshell console How to clear Java 9 JShell Console?
!!! Features and more !!!
More details over the links that gives it an upper hand over Single File Source Code Programs :
why and how Why and how do you use JShell?
import classpath for a project In JShell, how to import classpath from a Maven project
run an application via JShell How to run a java application with jshell?
set custom feedback modes Create custom feedback mode in jshell
load scripts on startup Different ways to load script on jshell startup
list active methods List all active methods in jshell
run a jshell file How to run a JShell File?
execute javascript with jshell How to execute a java script with jshell?
how to use method references in jshell Is there a way to use method references for top-level functions in jshell?
Related
Just exploring new release of Java, its new module system, and playing with jshell as well. Probably my question doesn't have too much sense, but I am just curious.
So I came up with the question: Is there any way to create a module in jshell? Or module can be only created in module-info.java?
Modules cannot be created using JShell currently and it is not a Goal of JShell either.
JShell Functionality
The JShell API will provide all of JShell's evaluation functionality.
The code fragments that are input to the API are referred to as
"snippets". The jshell tool will also use the JShell completion API to
determine when input is incomplete (and the user must be prompted for
more), when it would be complete if a semicolon were added (in which
case the tool will append the semicolon) and also how to complete
input when completion is requested with a tab.
A snippet must correspond to one of the following JLS syntax productions:
Expression
Statement
ClassDeclaration
InterfaceDeclaration
MethodDeclaration
FieldDeclaration
ImportDeclaration
A snippet may not declare a package or a module. All JShell code is placed in a single package in an unnamed module. The name of the package is controlled by JShell.
In fact trying to use a ModuleDeclaration within JShell is not a recognized syntax as well both evaluating directly or using the /edit:
Yet, the following options can be made to work out effectively to make use of existing modules within JShell along with the snippet evaluations -
--module-path <path>
Specify where to find application modules
--add-modules <module>(,<module>)*
Specify modules to resolve, or all modules on the
module path if <module> is ALL-MODULE-PATHs
I've been working on trying to get COBOL and Java to interact with each other on the mainframe, and have run into trouble with specifically the cob2 compiler, which is the Unix on the mainframe equivalent.
I haven't seen many user experiences with this compiler online, so I was wondering if I asked a more direct question, people would reveal their insight.
IBM has several examples of Java calling COBOL DLL's either directly or indirectly, but they ultimately boil down to compile the COBOL as a dll, use System.load, compile Java and run. These examples haven't worked for me for the following reasons.
When using cob2 with the -c option, it is purported to generate a .o object file. This has not happened for me, although it did generate an empty .lst file. I was able to get around this by simply skipping the -c step and compiling and linking using this series of commands:
` sh ${COB2HOME}/bin/cob2 -o ${DIR}/c2jcr.o
-qdll,thread,case=mixed ${DIR}/c2jcr.cbl;
${COB2HOME}/bin/cob2
-o ${DIR}/libc2jcr.so
-bdll,case=mixed ${DIR}/c2jcr.o
${JAVAHOME}/bin/j9vm/libjvm.x
${COB2HOME}/lib/igzcjava.x `
This appears to provide the .so library that is required for link with the Java program, but upon investigation of the load, and during run, the system declares that the LE CSECT CEESTART is not there.
Am I missing something in my cob2 library that has these LE modules, or somewhere in my scripting? I tried pulling in loads from the mainframe compiled with the LE modules intact and ENTRY CEESTART explicitly stated in the link step, but could not get any further than "UnsatisfiedLinkError" with "Internal Error".
Any wisdom is greatly appreciated, especially if you've gone down a completely different route to call COBOL from Java. Thank you very much.
After conferring with IBM, it turns out I had a couple things missing.
You must have a STEPLIB environment field set to the location of your COBOL compiler on the mainframe, so it can find your IGYCRCTL module.
Second, like other COBOL 5+ compiling, you must allocate a gargantuan amount of space in order to compile. 2 GB is not enough. Since I don't have permission to reallocate this in Unix, I ran a BPXBATCH job with REGION=0M.
After those two changes, -c compiles came out as normally. The "workaround" I provided in the question is completely incorrect. You must use:
sh ${COB2HOME}/bin/cob2 -c -qdll,thread,case=mixed ${DIR}/${COBPROG}.cbl
as your compile step, and the rest is just linkage.
I'm doing some basic java homework for a class on my new laptop - issue is, I can't seem to get the program to compile and run from my batch file using the directions the instructor gave me.
I've set the Path variable to my JDK inside the Environment Variables settings.
My program is a simple shipping program to keep track of shipment information - I have the program working flawlessly in NetBeans (which our instructor advised us to use for developing the code), but he's going to be testing them using batch files, so we're also advised to test them on our systems with one we create prior to turning them in - pretty straightforward.
Issue is, I cannot seem to get this to work. I've never done it before, but I've used .bat files to compile and run C++ programs, as well as using makefiles on a unix system, so I feel like I'm absolutely stupid for not figuring this out on my own, but none of my searches have returned any fruitful solutions that help at all.
My program consists of 3 .java files:
Shipment.java - an interface that contains abstracted methods that are implemented in the ShipmentHW1 class
ShipmentHW1.java - a class that implements the abstracted methods from Shipment and has constructors, etc to create a usable object
TestShipment.java - the main class of this program, which utilizes and creates ShipmentHW1 objects based on preset parameters. This is super duper basic stuff here, and again, it runs perfectly fine inside the NetBeans IDE.
The instructions given to us state to have the batch file inside the package directory (which in this case I've set aside a seperate folder on my desktop titled "shipping", which is the package name - shouldn't be any issues there), where the 3 .java files are located as well.
They say if you don't need to explicitly list the path to the JDK, then you can simply have
javac TestShipment.java
java TestShipment.java
pause
Afterwards I get errors talking about how it "cannot find symbol Shipment s = new ShipmentHW1();"
I've tried adding imports, but since they're in the same package it shouldn't even be an issue.
Directory path is
C:\Users\X\Desktop\shipping
All 7 files are contained within:
TestShipment.java
TestShipment.class
Shipment.java
Shipment.class
ShipmentHW1.java
ShipmentHW1.class
doHW1.bat
Does anyone have any idea? I can provide more information if I've been too vague
Also, I'm on Windows 8 if that makes any difference
Solved
Batch file now reads
javac TestShipment.java Shipment.java ShipmentHW1.java
cd ..
java shipment.TestShipment
pause
and it works like a charm. Anyone have any ideas why I had to call the package.class instead of just compiling it regularly?
Try doing
javac TestShipment.java
java TestShipment
pause
Without seeing the contents of TestShipment.java, I'll assume you have some dependency on the Shipment and ShipmentHW1 classes. As such, when you execute a program that uses the TestShipment class, you need to have the .class files for each of the three (and any other dependencies).
So you will have to compile Shipment.java and ShipmentHW1.java as well before running your java command. If they are in the same package, you're good, if not, you will have to specify an appropriate value for the -cp option.
When running java with a class name, you need to specify the fully qualified class name.
If your .java files are declared to be in the 'shipping' package, then you probably need to be running java from the parent directory of 'shipping', e.g.
cd <path>/shipping
javac TestShipment.java
cd ..
java shipping/TestShipment
I'm using Grails 2.1.0, and I have a Groovy class that I've written that's not dependent on services, controllers, or any of the other Grails goodness. It uses some .jar libraries and other classes that are already in the Grails classpath.
I want to:
Run the Groovy class (or a Java class, it shouldn't mattter) use the other libraries/classes that Grails already has on its classpath (not services, not controllers, none of that).
Be able to access the command line arguments [this is required]
Does not require bootstrapping the entire Grails environment (I need the classpath obviously, but nothing else)
Ideally, I'd like to be able to do something like this:
java -classpath (I_HAVE_NO_IDEA_HOW_TO_DETERMINE_THIS) com.something.MyClass param1 param2 param3
Things I've already looked into:
Using "grails create-script" which results in a Gant script.
Using "grails run-script"
The first one (using a Gant script) seems horribly wrong to me. Using an Gant script as some sort of intermediary wrapper seems to require bootstrapping the whole Grails environment, plus I have to figure out how to get a reference to the actual class I want to call which seems to be difficult (but I Am Not A Gant Expert, so enlighten me). =)
The second one (using run-script) sort of works... I've used this approach to call service methods before, but it has two problems: first, it bootstraps the entire Grails environment; second, there does not appear to be any way to pass the command-line arguments easily.
Really, I just want the stuff in the classpath (and my command-line parameters) and to be able to call the main() method of my class with minimial frustration. That being said, if you can come up with a working example of any sort that solves the issue (even if it involves some intermediary Gant or other class) I'll be happy to use that approach.
Thanks.
Update: A solution that works with a Gant task, still open to better ideas if anyone has any...
In scripts/FooBar.groovy
includeTargets << grailsScript("_GrailsInit")
target(main: "Runs a generic script and passes parameters") {
def myclass = classLoader.loadClass('com.whatever.scripting.GenericRunScript')
myclass.execute(args);
}
setDefaultTarget(main)
In src/groovy/com/whatever/scripting/GenericRunScript.groovy
package com.whatever.scripting
class GenericRunScript {
public static execute(def args) {
println "args=" + args.inspect()
}
}
Then from the command line, at while in the root directory of the Grails project:
$ grails compile
| Environment set to development.....
| Compiling 2 source files.
$ grails foo-bar test one two
| Environment set to development....
args='test\none\ntwo'
Note 1: When I first did this, I kept forgetting the compile statement, so I added that in.
Note 2: Yes, the args are separated by carriage returns; fixing that is left as an exercise to the reader.
The way described above would work but all grails facility will be gone including domains and dependencies.
If you require everything that you have defined in your grails project, the run-script command will do the trick
grails run-script [path to your groovy file]
http://grails.org/doc/latest/ref/Command%20Line/run-script.html
As described in http://grails.org/doc/latest/guide/commandLine.html, you can include targets _GrailsClasspath and _GrailsArgParsing, and whatever else you need. For example, if you want to parse command-line arguments without creating a second script:
$ grails create-script ArgsScript
| Created file scripts/ArgsScript.groovy
Now edit the script scripts/ArgsScript.groovy as follows:
includeTargets << grailsScript("_GrailsArgParsing") // grailsScript("_GrailsInit")
target(main: "The description of the script goes here!") {
println argsMap
for (p in argsMap['params'])
println p
}
setDefaultTarget(main)
See the result:
$ grails args-script one two three=four
| Environment set to development....
[params:[one, two, three=four]]
one
two
three=four
Update: well, it is not as easy as I thought. Basically, you can either run a script as a Gant task, e.g. by doing grails myscript, or as a script, e.g. by doing grails run-script src/groovy/MyScript.groovy. In the first case you have access to parameters, as I already explained, but you still miss some of the Grails environment, which is, perhaps, a bug. For example, you can't really access scripts or classes defined in src/groovy/ from a Gant task. On the other hand, as was already discussed, if you use run-script, you can't get the arguments.
However, you can use System.getProperty to pass command-line arguments with the -Dproperty=value syntax. Also see Java system properties and environment variables
Is there a way to run or simulate running Java statements (kind of like IDLE - the Python GUI) without compiling and running the executable? I want to quickly test statements to see if they work. Thanks.
Yep, you can use Eclipse, create a single project, and create a Scrapbook Page in that project.
You can also specify import statements: http://www.informit.com/articles/article.aspx?p=31789&seqNum=3
Scrapbook pages get their classpath
from the containing project's build
path. If in a scrapbook page you want
to reference a Java element that is
not on the build path of the
containing Java project, you need to
add to the Java project's build path.
Scrapbook pages also allow you to
specify import statements. You do this
by selecting Set Imports from the
context menu of a scrapbook page or
Set Import Declarations for Running
Code from the toolbar. You need to set
import statements for references to
Java declarations in your projects.
This is a common oversight. If the
type or package you are attempting to
import is not listed in the Add
dialog, it means you need to add it to
the build path of the project
containing the scrapbook page. If you
are referencing an element that has
multiple declarations, you will need
to add an import statement to uniquely
identify the element.
Edit: Got another solution too: http://ideone.com. It's an online IDE and debugging tool. You can see an example here: http://ideone.com/98sA8, but it looks like you have to set up a bit more than on a scrapbook page.
Edit 2:
Nowadays in Java 11, if it's a simple app in a single file you can run it directly from the java command (on the command line) which will handle all the compilation for you behind the scenes:
java HelloWorld.java
This is useful for students, as they can get started with Java without learning all of the javac compilation routine.
As of Java 11 (JEP 330) it is now possible to run Java files directly with the java tool:
java Factorial.java 3 4 5
is informally equivalent to
javac -d <memory> Factorial.java
java -cp <memory> Factorial 3 4 5
Java also added support for "shebang" files.
For more details see:
http://openjdk.java.net/jeps/330
Using Eclipse, you can create a Scrapbook page which will allow you to do exactly this.
Caveats:
You need to use full binary class names for anything outside of java.lang
You need to select the code (standard text selection) that you want to run
There are three different methods for running -- Inspect, Display, and Run. Inspect and Display are virtually the same, showing you the result of the last statement in your code (so you don't need to print it or anything), Run runs the selected code and dumps any output to the console view.
Never used it, but BeanShell seems to do what you want
You should be able to use Beanshell to do this:
http://www.beanshell.org/download.html
Your other alternative, if you're using Eclipse, is to make use of the scrapbook functionality:
http://help.eclipse.org/helios/index.jsp?topic=/org.eclipse.jdt.doc.user/tasks/task-create_scrapbook_page.htm
You can accomplish this with Groovy and the Groovy Console, with the caveat that you'd need to know how to express whatever you are trying to express in Java in the Groovy language:
you might want to checkout janino http://docs.codehaus.org/display/JANINO/Home also ..
JGrasp is the best solution. There is a thing called interactions, that's perfectly fine.
Use JShell, which is included by default starting from JDK 9. It is command-line based Read Eval Print Loop (REPL), where you can enter Java code, and get the results immediately.