简体   繁体   English

我想在 JDK 8 中使用 `jshell`

[英]I'd like to use `jshell` with JDK 8

I tried out the JDK 11 jshell recently and liked being able to interactively test out what's documented in core Java.我最近试用了 JDK 11 jshell ,喜欢能够以交互方式测试核心 Java 中记录的内容。 My company is still tied to releasing with Java 8 though.不过,我的公司仍然与 Java 8 一起发布。 So I thought I'd try and see if I can use the jshell to work with JDK 8.所以我想我会尝试看看我是否可以使用jshell来处理 JDK 8。

Edit to try and explain what seems unclear: I want to use JShell, but use the Java 8 APIs for interactive mode, scripts, completion, JavaDoc etc.编辑以尝试解释似乎不清楚的内容:我想使用 JShell,但将 Java 8 API 用于交互模式、脚本、完成、JavaDoc 等。

My mental model of what the jshell was doing is: It is built with the JDK it was provided with, it therefore runs on the JRE it was built for, but I thought it loaded the JavaDoc, Auto-completions, from a JDK collection of jars, and ran the interactive scripts against another instance of the JVM, not necessarily the one with the same version as it is running on.我对jshell正在做的事情的心理模型是:它是用它提供的 JDK 构建的,因此它在它为其构建的 JRE 上运行,但我认为它从 JDK 集合中加载了 JavaDoc,自动完成jars,并针对另一个 JVM 实例运行交互式脚本,不一定是与它运行的版本相同的实例。 So I thought I could control that second part with the JAVA_HOME environment variable.所以我想我可以用JAVA_HOME环境变量控制第二部分。

On a Mac, my simple first attempt was to:在 Mac 上,我简单的第一次尝试是:

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/ \
/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/bin/jshell

But it's not obvious to me that this is working at all (I'll wrap some lines):但对我来说这并不明显(我会换行):

jshell> System.getProperties()
$3 ==> {gopherProxySet=false, awt.toolkit=sun.lwawt.macosx.LWCToolkit,
java.specification.version=11, sun.cpu.isalist=, sun.jnu.encoding=UTF-8,
java.class.path=., java.vm.vendor=Oracle Corporation, sun.arch.data.model=64, 
java.vendor.url=http://java.oracle.com/, user.timezone=, os.name=Mac OS X, 
java.vm.specification.version=11, sun.java.launcher=SUN_STANDARD, user.country=US,
sun.boot.library.path=/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/lib,
sun.java.command=jdk.jshell.execution.RemoteExecutionControl 55110, 
jdk.debug=release, sun.cpu.endian=little, user.home=/Users/lamblin,
user.language=en, java.specification.vendor=Oracle Corporation, 
... 
patch.level=unknown,
java.library.path=/Users/lamblin/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:., 
java.vendor=Oracle Corporation, java.vm.info=mixed mode,
java.vm.version=11.0.1+13-LTS, sun.io.unicode.encoding=UnicodeBig,
java.class.version=55.0}

jshell> System.getenv("JAVA_HOME")
$4 ==> "/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/"

jshell> exit

Why?为什么? well the Stream.ofNullable(T) is new in Java 9 and while I'd like it to tell me that it's not in Java 8, it instead works pretty normally. Stream.ofNullable(T)是 Java 9 中的新内容,虽然我希望它告诉我它不在 Java 8 中,但它可以正常工作。

jshell> Stream.ofNullable(null).iterator().hasNext()
$3 ==> false

jshell> Stream.ofNullable("hi").iterator().hasNext()
$4 ==> true

jshell> Stream.ofNullable(
Signatures:
Stream<T> Stream<T>.<T>ofNullable(T t)

<press tab again to see documentation>

jshell> Stream.ofNullable(
Stream<T> Stream<T>.<T>ofNullable(T t)
Returns a sequential Stream containing a single element, if non-null, otherwise returns an
empty Stream .

Type Parameters:
T - the type of stream elements

Parameters:
t - the single element

Returns:
a stream with a single element if the specified element is non-null, otherwise an empty stream

<press tab again to see all possible completions; total possible completions: 544>

jshell> Stream.ofNullable(

Perhaps what I want isn't possible with this jshell .也许这个jshell不可能实现我想要的。 I had started thinking it was when I saw a video using jshell in NetBeans on JDK 8. This video may have been misstating what was actually accomplished.当我看到一个在 JDK 8 上的 NetBeans 中使用jshell的视频时,我开始认为这是。该视频可能误报了实际完成的内容。

I did find that changing the class-path isn't what I'm after because that stops the jshell from being able to load classes it needs.我确实发现更改类路径并不是我所追求的,因为这会阻止jshell加载它需要的类。

So not: /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/bin/jshell --class-path /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/*所以不是: /Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/bin/jshell --class-path /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/*

It is possible to start the jshell normally and then add one of the JRE 8 jars to the class path with /env -class-path /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar .可以正常启动jshell ,然后使用/env -class-path /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar将JRE 8 jar之一添加到类路径/env -class-path /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar This can be done with with all the jars in jre/lib but it won't unload or replace what was loaded, so it doesn't end up giving you an environment limited to running Java 8 snippets.这可以使用jre/lib所有 jar 完成,但它不会卸载或替换已加载的内容,因此它最终不会为您提供仅限于运行 Java 8 片段的环境。

This is not using using jshell in Java 8.这不是在 Java 8 中使用jshell

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/ \
/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/bin/jshell

Why?为什么? Because JDK tools don't actually use $JAVA_HOME to decide which JVM to use.因为 JDK 工具实际上并不使用 $JAVA_HOME 来决定使用哪个 JVM。 Instead the decision is made by the executable (or wrapper script) based on its file location.而是由可执行文件(或包装脚本)根据其文件位置做出决定。

But you can confirm this by running jshell -version .但是您可以通过运行jshell -version来确认这一点。 (Note: only one - !!) (注:只有一个- !!)


If you download the OpenJDK source, you can see that jshell is mostly implemented in Java.如果下载 OpenJDK 源码,可以看到jshell大多是用 Java 实现的。 And it has a main method.它有一个主要的方法。 So you might be able to compile the jshell classes with a Java 8 compiler.因此,您可以使用 Java 8 编译器编译jshell类。 But that is likely to fail 1 , because jshell knows about modules, and that means it has dependencies on module-related API changes that were made in Java 9.但这很可能会失败1 ,因为jshell知道模块,这意味着它依赖于 Java 9 中与模块相关的 API 更改。

But ... why bother?但是……何必呢?

Why?为什么? well the Stream.ofNullable(T) is new in Java 9 and while I'd like it to tell me that it's not in Java 8, it instead works pretty normally. Stream.ofNullable(T)是 Java 9 中的新内容,虽然我希望它告诉我它不在 Java 8 中,但它可以正常工作。

  1. The Java 8 compiler will tell you that. Java 8 编译器会告诉你。 So will an IDE, assuming you set the platform dependencies.假设您设置了平台依赖项,IDE 也是如此。

  2. You might be able to use the -C option to get jshell to compile your code against the Java 8 APIs.您也许可以使用-C选项让jshell编译您的代码以针对 Java 8 API。


1 - If you put in the effort to work around these anticipated dependencies, and other Java 9+ dependencies in the jshell classes, then you will have succeeded in backporting it to Java 8. Fame and fortune awaits you :-) 1 - 如果您努力解决这些预期的依赖项以及 jshell 类中的其他 Java 9+ 依赖项,那么您将成功地将其向后移植到 Java 8。名利等着您:-)

Here's what I do - I have both Java 8 and Java 17, I escape to Java 17 momentarily for the jshell session ...这就是我所做的 - 我有 Java 8 和 Java 17,我暂时转而使用 Java 17 进行 jshell 会话......

jshell() {
  export JAVA_HOME=/opt/homebrew/Cellar/openjdk/17/libexec/openjdk.jdk/Contents/Home
  /usr/bin/jshell "$@"
  export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home
}

I add the above bash function to my ~/.bash_profile我将上面的 bash 函数添加到我的~/.bash_profile

While this may not be the perfect way, at least I can try out few things that are common across Java 8 and Java 17 ...虽然这可能不是完美的方式,但至少我可以尝试一些在 Java 8 和 Java 17 中通用的东西......


~ java -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed mode)

~ jshell
|  Welcome to JShell -- Version 17
|  For an introduction type: /help intro

jshell> String s = "abc"
s ==> "abc"

jshell> s
s ==> "abc"

jshell> s.charAt(1)
$4 ==> 'b'

jshell> /exit
|  Goodbye

~ java -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (Temurin)(build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (Temurin)(build 25.302-b08, mixed mode)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM