个人创作约定:本人声明,本人创作的所有文章均为本人原创。如果有参考任何文章,它将被标记。如有疏漏,欢迎大家批评指正。如果您在网上发现有人抄袭本文,请举报并积极向本github仓库提交issue。感谢大家的支持~如果不喜欢这个文字版,可以参考官方JavaInsiderNews第20期-关于Java18你想知道的一切:-B站视频地址-知乎Java18视频地址今天(2022-3-22)发布了GA版本。今天也是我和宝宝领证一周年。为了纪念今天,特此奉献上文-关于Java18你想知道的一切正式发布新特性SimpleHTTPserver相关JEP:JEP408:SimpleWebServer如果想了解更多用法,请观看此视频:[JavaInsiderNews第16期[熟肉]-Java18web服务器](https://mp.weixin.qq.com/s?__...)为了方便大家快速搭建HTTP服务器挂载一些静态文件,实现快速并且易于测试,并演示一定的这些功能,JDK18自带了一个简单的HTTP服务器——在bin目录下有一个额外的工具jwebserver。可以通过以下命令行启动一个简单的HTTP服务器:可以指定的参数包括:-baddr或--bind-addressaddr:指定绑定地址,默认addr为:127.0.0.1或::1(loopback)-ddir或--directorydir:指定挂载目录,默认dir为当前目录,挂载后即可得到文件夹-olevel或--outputlevel的内容:指定日志级别,默认levelisinfo(canbe:none|info|verbose)-pportor--port端口:指定端口,默认端口8000访问可以看到这个相当于一个简单的文件服务器挂载目录:在同时,还可以在启动的控制台看到请求的访问日志:127.0.0.1--[March21st,2022:14:25:48+0800]"GET/HTTP/1.1"200-ItonlyservesHEADandGET请求,不支持认证、访问控制、加密等。可以使用com.sun.net.httpserver下的类来自定义这个HTTP服务器的配置,自定义HttpHandler、Filter等,例如:JEPrelatedtoInternetAddressResolutionSPI:JEP418:Internet-AddressResolutionSPIwas最初在Java中,互联网地址解析是一个内置的解析器,它使用本地“主机”文件和DNS的组合;Java18之后,定义了SPI用于互联网地址解析,这样除了内置的解析器之外,还可以使用'java.net.InetAddress'其他解析器。这主要是为了:为ProjectLoom做准备:'java.net.InetAddress'的解析当前阻塞在OS调用上。这对Loom的虚拟线程来说是有问题的,因为这也会阻塞虚拟线程,使调度程序无法切换到另一个虚拟线程。通过将其抽象为SPI来为非阻塞DNS解析提供另一个解析器。兼容新网络协议:可实现DNSoverQUIC/TLS/HTTPS等新解析协议的无缝集成。CustomRetrofitParsingResults:为框架和应用程序提供对解析结果的更多控制,并允许使用自定义解析器对现有库进行改造。更好的测试:比如可以实现自己的SPI来模拟远程请求实际解析到一些本地地址等。这个SPI是哪个类,可以参考[java.util.ServiceLoader]()的使用,以及通过里面的api指定如下SPI接口的实现:DeprecateForRemovalrelatedJEPofjava.net.spi.InetAddressResolverProviderFinalization:JEP421:DeprecateFinalizationforRemovalJavafinalization是Java从一开始就有的特性。它最初的设计目的是为了让我们避免资源泄漏:当没有人引用持有资源的实例时,然后执行一段代码来回收资源。按照这个思路,你会认为垃圾回收器知道什么时候回收一个对象,所以就用垃圾回收机制来执行这段代码。所以设计了Object的finalize()方法,Java类可以重写这个方法,填入关闭资源的代码。当对象被回收时,这段代码会被调用。但是这种机制带来了如下问题:假设你的JVM老年代增长的很慢,如果你需要finalize的对象进入老年代,那么这个对象可能很长时间都不会被回收。假设你需要finalize的对象突然变多了,创建这样的对象的速度比GC收集并执行finalize()方法的速度还要快,这会造成雪崩,因为无法确定哪个线程执行了finalize()方法和顺序是什么这些finalize()方法,所以这个方法里面不能有影响线程安全的代码,随机引用外部对象导致对象“复活”,而且,这个Finalization还是一个历史包袱,所有的垃圾收集器代码都必须不断维护执行这些finalize()方法的机制,影响这些垃圾收集器的迭代,并且由于Finalization的存在,GC占用的内存页增加。ZGC估计1.5%的内存使用量仅用于Finalization。因此,实际上,Object的finalize()方法从Java9开始就被标记为Deprecated,现在从Java18开始正式标记为Deprecated移除,也就是说这个方法在不久的将来会被彻底移除。如何验证移除Finalization是否对你的项目有影响?如果你使用JFR,你可以使用Java18之后添加的JFR事件jdk.FinalizerStatistics来查看你的JVM中是否有Finalization。如果你还没有启用JFR,那我推荐你使用JFR,它非常好用。参考:JFRFullSolution如果不想通过JFR,那么可以先记录:程序运行时的JVM内存使用情况,建议开启NativeMemoryTracking,参考:JVM相关-深入理解System.gc()进程相关文件描述符DirectBuffer和MMAPBufferusage的数量:可以通过JMXMBeans查看,例如:记录后,在启动参数中加上--finalization=disabled,这个参数使所有的Finalization机制无效,比较内存使用情况,判断是否依赖Finalization。默认编码是UTF-8相关的JEP:JEP400:UTF-8byDefaultJava中的很多方法都有字符编码集的参数,例如:newString(newbyte[10]);newString(newbyte[10],字符集.defaultCharset());如果不通过,就是使用系统默认的字符集,比如在Linux和MacOS上一般使用UTF-8,但在Windows上就不是UTF-8了。从Java18开始,默认的字符集不再与操作系统相关,是UTF-8。如果你运行的操作系统是Linux、MacOS,或者你的启动参数本身有-Dfile.encoding=COMPAT,那么基本上对你没有影响。如果想改回原来根据操作系统环境指定默认字符集的方式,可以使用这个启动参数:-Dfile.encoding=COMPAT通过方法句柄(MethodHandle)重新实现Java反射接口相关JEP:JEP416:ReimplementCoreReflectionwithMethodHandles在JDK18之前,存在三种用于反射操作的JDK内部机制:字节码存根(Method::invoke,Constructor::newInstance)由虚拟机本地方法动态生成,字段访问依赖于不安全类(Field::getandset):主要在java.lang.reflect下方法句柄(MethodHandle类):主要在java.lang.invoke下每次给Java增加一些新的结构特性,比如Record,都需要同时修改这三个代码太费力了。因此在Java18中,第二个API是使用java.lang.invoke下的类来实现的,以减少日后添加新的语言特性所需的工作量。这也是为ProjectValhalla的原生值类型做准备(可以在栈上分配,类似于C语言中的struct,其他语言中的inlineclass)。CompilableJavadoccodesnippetrelatedJEP:JEP413:CodeSnippetsinJavaAPIDocumentation干净、整洁、更新及时的API文档和标准化的例子会让你受益匪浅,如果API文档的代码可以编译,就可以遵循如果你的源码改一下就更完美了,Java18给了Javadoc这些特性。我们来尝试写一个Maven项目(代码库地址:https://github.com/HashZhang/...)首先,我们要在普通maven的src/main/java和src/test/java之外添加一个新的projects目录src/demo/java用于存放示例代码。因为我们不想把示例代码打包到最终发布的jar包中,示例代码还需要编译,所以我们把这个示例代码目录标记为测试代码目录(为什么不放在src/test/java,因为我们还是要区分Samplecode和unittestcode):需要maven插件执行生成javadoc,需要指定代码段扫描目录(即可执行代码段文件所在目录)位于你的源代码中,这个目录在这里和源代码目录src/main/java隔离开来,是src/demo/java):首先,我们创建我们的API类,即:如你所见,我们在注释的代码段中指定要读取的文件和区域,下面我们来编写示例代码:从示例代码中,我们可以看到引用区域的指定(位于@start和@end之间)。目前的项目结构是:执行mvnjavadoc:javadoc,在target/site目录下可以看到生成的Javadoc,里面可以包含你项目中的代码段:也可以高亮你的一些注释,或者使用CSS编辑样式,我不会在这里详细介绍。新预览特性Switchpatternmatching(secondSecondpreview)Java17中的第一个预览Java18中的第二个预览Java17正式发布了SealedClass(封闭类),基于这个特性,我们可以在Switch中进行模式匹配,例如一个简单的例子:在某些情况下,我们可能想枚举一个接口的所有实现类,例如:我们如何确定我们已经枚举了所有的Shapes?SealedClass的特性为我们解决了这个问题。SealedClass在声明的时候可以确定哪些类可以继承这个类:SealedClass(可以是抽象类,也可以是接口)需要在声明的时候指定所有实现类的名字。对于继承类,有如下限制:SealedClass的继承类必须和SealedClass在同一个模块下。如果没有指定模块,则必须在同一个包下。每个被继承的类必须直接继承SealedClass,不能间接继承每个继承类必须是以下三种类型之一:final类,JavaRecord本身就是一个final密封类,可以进一步指定哪些子类会实现非sealedclass,也是一个扩展,但是打破了SealedClass的限制,SealedClass不知道也不关心这种继承类会有哪些子类。例如:添加Switch模式匹配后,可以重写上面的area方法(需要在编译参数和启动参数中添加--enable-preview开启预览):如果这里不写default,还有,如果有类型缺失,例如:那么会报编译错误,这是switch模式匹配的穷举检查。在第二个预览版中,主要修复了包含参数泛型的封闭类的详尽性检查。即有以下封闭类:对于以下代码,穷举检查不会误报编译错误:该功能还在完善中,大家可以试用,也可以在这里提交意见交流:https://邮件。openjdk.java.net/pipermail/amber-spec-experts/2022-February/003240.htmlIncubatingnewfeatures与内存API相关的外部函数(第二次孵化)JEP:Java17发布的第一次孵化18年发布的第二次孵化还没有尚未决定何时发布。第一个预览这是ProjectPanama(以巴拿马运河命名)带来的hatch中一个非常重要的特性,就像连接太平洋和大西洋的纽带巴拿马运河一样,ProjectPanama希望连接Java虚拟机使用外部非Java库。此功能是其中最重要的部分。该特性的主要目的是:首先,提供一个性能和安全特性相似的ByteBufferAPI的替代方案,并修复原始API的一些缺点(许多需要访问堆外内存的库,如Netty操作直接内存作为缓冲池会受益)其次,通过用更多面向Java的API替换JNI,原生库更易访问,即可以通过Java代码直接调用系统库最后,替换sun.misc.Unsafe中的内存访问API已被替换为更易于使用的包。下面是一个使用ForeignLinkerAPI在Windows上使用Java直接调用user32库中的MessageBoxW函数的例子:有兴趣的可以看这个视频:ForeignLinkerAPI:JavanativeaccesswithoutC|现代爪哇|JDK16|HeadCrashingInformatics27目前一些有趣的项目正在试验外部函数和内存API:sqlite-jdbcnetty(使用ProjectPanama重构BufferApi)ElasticSearchLuceneVectorAPI(第三次孵化)相关JEP:firstincubationinJava16Thesecondhatch在Java17中第三次孵化在Java18中,这也是ProjectPanama的重要组成部分。这些应用程序中最主要的是使用CPU的SIMD(单指令多数据)处理,它通过程序提供多通道数据流,可能有4通道或8通道或任何数量的通道,单个数据元素流经这些通道。并且CPU同时在所有通道上并行组织操作,可以大大提高CPU吞吐量。通过VectorAPI,Java团队正在努力使使用Java代码的Java程序员可以直接访问它;过去,他们不得不在汇编代码级别编写矢量数学,或者使用带有Intrinsic的C/C++,然后通过JNI将其提供给Java。一个主要的优化点是循环,过去的循环(标量循环),一次在一个元素上执行,而且速度很慢。您现在可以使用VectorAPI将标量算法转换为更快的数据并行算法。使用Vector的例子:注意使用incubatingJava特性需要额外的启动参数来暴露模块,这里是--add-modulesjdk.incubator.vector,javac编译和java运行需要添加这些参数,使用IDEA,即:测试结果:其他用途,请参考:fizzbuzz-simd-style,这是一篇比较有意思的文章(虽然这个性能优化感觉不仅仅是SIMD的缘故,还有算法优化的缘故,哈哈)关于一些更详细的使用和设计思路可以参考这段音频:VectorAPI:SIMDProgramminginJava微信搜索“我的编程喵”关注公众号,每天扫一扫,轻松提升技术,赢各种优惠:我会经常发布各种框架官方社区的一些好消息视频资料并添加个人翻译字幕到以下地址(包括上面的公众号),欢迎关注:知乎:https://www.zhihu.com/people/...B站:https://space.bilibili.com/31...
