为什么笔者会写这篇文章,主要还是Java更新支持来说。首先我们要知道LTS版本JDK和普通JDK的区别。
(LTS版本,Long-Term-Support),Java 大版本周期变化后的长期支持版本。
1.各个JDK版本介绍
1.1.JDK8新特性(2014年初)(LTS版本)
1、Lambda表达式
2、函数式编程
3、接口可以添加默认方法和静态方法,也就是定义不需要实现类实现的方法
4、方法引用
5、重复注解,同一个注解可以使用多次
6、引入Optional来避免空指针
7、引入Streams相关的API
8、引入新的Date/Time相关的API
9、新增jdeps命令行,来分析类、目录、jar包的类依赖层级关系
10、JVM使用MetaSpace代替了永久代(PermGen Space)
重要特性:Lambda表达式、函数式接口、方法引用、Stream流式API、采用MetaSpace代替了永久代(PermGen Space)
1.2.JDK9新特性(2017年9月)
1、接口方法可以使用private来修饰
2、设置G1为JVM默认垃圾收集器
3、支持http2.0和websocket的API
重要特性:主要是API的优化,如支持HTTP2的Client API、JVM采用G1为默认垃圾收集器
1.3.JDK10新特性(2018年3月)
1、局部变量类型推断,类似JS可以通过var来修饰局部变量,编译之后会推断出值的真实类型
2、并行Full GC,来优化G1的延迟
3、允许在不执行全局VM安全点的情况下执行线程回调,可以停止单个线程,而不需要停止所有线程或不停止线程
重要特性:通过var关键字实现局部变量类型推断,使Java语言变成弱类型语言、JVM的G1垃圾回收由单线程改成多线程并行处理,降低G1的停顿时间
1.4.JDK11新特性(2018年9月)(LTS版本)
1、ZGC,ZGC可以看做是G1之上更细粒度的内存管理策略。由于内存的不断分配回收会产生大量的内存碎片空间,因此需要整理策略防止内存空间碎片化,在整理期间需要将对于内存引用的线程逻辑暂停,这个过程被称为"Stop the world"。只有当整理完成后,线程逻辑才可以继续运行。(并行回收)
2、Flight Recorder(飞行记录器),基于OS、JVM和JDK的事件产生的数据收集框架
3、对Stream、Optional、集合API进行增强
重要特性:对于JDK9和JDK10的完善,主要是对于Stream、集合等API的增强、新增ZGC垃圾收集器
1.5.JDK12新特性(2019年3月)
1、Shenandoah GC,新增的GC算法
2、switch 表达式语法扩展,可以有返回值
3、G1收集器的优化,将GC的垃圾分为强制部分和可选部分,强制部分会被回收,可选部分可能不会被回收,提高GC的效率
重要特性:switch表达式语法扩展、G1收集器优化、新增Shenandoah GC垃圾回收算法
1.6.JDK13新特性(2019年9月)
1、Socket的底层实现优化,引入了NIO;
2、switch表达式增加yield关键字用于返回结果,作用类似于return,如果没有返回结果则使用break;
3、ZGC优化,将标记长时间空闲的堆内存空间返还给操作系统,保证堆大小不会小于配置的最小堆内存大小,如果堆最大和最小内存大小设置一样,则不会释放内存还给操作系统;
4、引入了文本块,可以使用"""三个双引号表示文本块,文本块内部就不需要使用换行的转义字符;
重要特性:ZGC优化,释放内存还给操作系统、socket底层实现引入NIO
1.7.JDK14新特性(2020年3月)
1、instanceof类型匹配语法简化,可以直接给对象赋值,如if(obj instanceof String str),如果obj是字符串类型则直接赋值给了str变量;
2、引入record类,类似于枚举类型,可以向Lombok一样自动生成构造器、equals、getter等方法;
3、NullPointerException打印优化,打印具体哪个方法抛的空指针异常,避免同一行代码多个函数调用时无法判断具体是哪个函数抛异常的困扰,方便异常排查;
1.8.JDK15新特性(2020年9月)
1、隐藏类 hidden class;
2、密封类 sealed class,通过sealed关键字修饰抽象类限定只允许指定的子类才可以实现或继承抽象类,避免抽象类被滥用;
1.9.JDK16新特性(2021年3月)
1、ZGC性能优化
2、instanceof模式匹配
3、record的引入
JDK16相当于是将JDK14、JDK15的一些特性进行了正式引入。
1.9.JDK17新特性(2021年9月)(LTS版本)
1、正式引入密封类sealed class,限制抽象类的实现;
2、统一日志异步刷新,先将日志写入缓存,然后再异步刷新;
虽然JDK17也是一个LTS版本,但是并没有像JDK8和JDK11一样引入比较突出的特性,主要是对前几个版本的整合和完善。
2.Java 17环境安装
2.1.安装包获取
官网下载http://jdk.java.net/17/
本人资源下载
不需要积分
2.2.安装教程
点击下一步
更换目录
点击关闭
至此,安装完成,如果你之前只安装过Java 8以前的版本,可能有点蒙蔽,貌似没有jre啊?
其实这个在JDK9的时候就已经取消了。
接下来我们看下我们的环境
2.3.环境变量配置
在配置环境变量以前,我们先考虑一个问题,就是现在我们还需要配置java环境变量吗?
首先,我们先不配置java环境变量,看看能否执行javac命令,很神奇,居然能直接执行。
这时候我们编写如下代码,别用任何IDE,直接用记事本编写,看看能不能运行这个java文件。
public class HelloJava17 {
public static void main(String[] args) {
System.out.println("hello java 17!");
}
}
这里笔者提一个超级简单的问题,java命令和javac命令的区别?小伙伴可能会说,java是运行*.class文件,java是将*.java文件转变成*.class文件。
javac HelloJava17.java
java HelloJava17.class
通过下面这个图,可能就让人蒙蔽了。首先我们看到是没有class文件的,我们直接用java命令执行java文件。结果居然成功运行,好不合理,至于这个特性是不是java17还是之前的版本,这里我们就不讨论了。
第二个问题,那就是刚才我们明明没有配置java环境变量,为啥就能使用java嗯?
现在让我们检查下我们的环境变量
可以看到笔者的配置的环境变量是java8,但是查看java版本,居然是17。
查看path
现在我们第一行的环境变量移动到java8后面
C:\Program Files\Common Files\Oracle\Java\javapath
可以看到变成java 8了。
我们看看这个Oracle\Java\javapath下有什么。我们可以看到提供了这四个java命令,其实这个功能在java8的安装包以后,都有这个功能,就是安装的时候,给我们默认配置了下面这个路径的环境变量,位置还是第一个。所以现在也就解释了,为什么在我们安装java17以后,我们不用配置环境变量还是能执行我们的java代码。
接下来我们在去看看java安装环境下有哪些命令,如果你需要用到下面这些其他的命令,当然你可以配置环境变量。用不到也可以不用配置。
如果使用 1.5 以上版本的 JDK,不用设置 CLASSPATH 环境变量,也可以正常编译和运行 Java 程序。
如果使用1.8以后的安装版本,java环境变量都可以直接不用配置了,除非你要用到的高级特性在默认路径下没有。
修改JAVA_HOME将其设置为JDK17的安装路径
将所有的Oracle\Java\javapath的环境中变量全部移动到java17之后,或者直接删掉
2.4.IDE中使用JDK 17
笔者这里使用的STS。目前笔者使用的STS版本是4.12,IDE默认的JDK支持只到16。因此这里我在IDE中配置我本地安装的JDK17
创建一个Spring Boot项目,选择Java vesrion为17。
相关组件,这里我只做演示,暂时只使用Spring Web(即Spring和Spring MVC)
创建项目的时候,明明选择的是Java17,但是由于IDE不支持17,只能支持到16,因此该SpringBoot项目创建后,看到IDE是16。
这时候在IDE中,配置我们安装的JDK17
这时候JDK变成了17.
接下来,我们跑一段Demo代码,获取java版本
@RestController
public class DemoController {
@GetMapping("/demo/hello")
public Map<String,String> helloJava17(){
Map<String,String> result = new ConcurrentHashMap<String, String>();
result.put("code", "200");
result.put("msg", "hello java 17!");
result.put("javaVersion",System.getProperty("java.version"));
result.put("vmVersion", System.getProperty("java.vm.version"));
return result;
}
}
运行结果如下图所示。
2.5.java17运行部署包
接着maven编译打包一下
这是时候如果我们用java方式启动这个jar包,会怎么样?
启动没问题,运行结果也没问题。