jdk9和jdk11

一、JDK9

1、模块化系统(最主要的特性)

1、为什么引进模块化?
运行一个简单的hello world程序,在JDK8中你需要几百兆的JRE环境,有些jar可能并不是你运行程序所必须的,浪费了很多空间。但是在 JDK 9中,JDK被分成了大约94个modules,在用的时候引入你需要的module就行了。
在这里插入图片描述
2、什么是模块化
本质上讲,模块的概念就是package外再裹一层。
也就是说,用模块来管理各个package,通过声明某个package暴露,不声明默认就是隐藏。

3、实现的目标

  • 减少内存的开销
  • 只需必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
  • 改进javase平台,使其可以适应不同大小的计算设备
  • 改进其安全性,可维护性,提高性能

4、使用
新建两个子模块,分别新建module-info文件
在这里插入图片描述
工程1的module-info:
注意
1、项目的pom文件中导入了依赖,但是如果使用了模块化机制,如果想用依赖中的类,就先要导入依赖对应的模块,如果不使用模块化机制,依赖中的类是可以直接使用的。
2、只有用了module-info,才会以模块化的形式编译程序,这时,一个第三方jar才可以认为是一个Java module,目前Java生态中大多数的库还没有考虑加上module-info模块化,所以一个jar导出的是jar里的所有包

module demo {
    //引用第三方模块,由于这些模块还没有考虑到加上module-info模块化,所以一个jar导出的是jar里的所有包
    requires lombok;
    requires spring.boot.autoconfigure;
    requires spring.boot;
    //导出模块
    exports com.example.demo.bean;
}

工程2的module-info:

module javatest {
    requires demo;
    requires spring.boot.autoconfigure;
    requires spring.boot;
    requires aoptest;
}

通过这种机制,工程2中就能只用工程1中com.example.demo.bean下的类,而以前,可能是直接导入工程1的依赖,把工程1的所有类到都引入到工程2中来。

2、Jshell(java9开始)

下面JDK11有。

3、多版本兼容jar包

多版本兼容 JAR 功能能让你创建仅在特定版本的 Java 环境中运行库程序时选择使用的 class 版本。
https://www.jianshu.com/p/972c7d531094

4、接口中定义私有方法

面试题:抽象类和接口异同?
①声明方式不同:接口使用interface,抽象类使用class
②内部的结构不同

  • jdk8之前:接口只能声明全局变量和抽象方法,但是抽象类就比较自由了,和普通的类差不多
  • jdk8:接口可以声明静态方法和默认方法,并且是可以实现的
  • jdk9:接口可以声明私有方法

③接口和抽象类都不能实例化,以多态的方式使用
④接口是多实现的,抽象类是单继承的

在这里插入图片描述

5、语法改进:砖石操作符使用升级

能够与匿名实现类共同使用砖石操作符。
例如:

    public static void main(String[] args) {
        //创建一个继承于hashset的匿名子类的对象
        Set<String> set = new HashSet<>(){};
        set.add("AA");
        set.add("BB");
        set.add("CC");
        for (String s : set) {
            System.out.println(s);
        }
    }

6、语法改进:try语句的升级

    public static void main(String[] args) {
        InputStreamReader reader=new InputStreamReader(System.in);
        //jdk8是不允许这样做的
        try(reader){
            //读取数据的过程,略
            reader.read();
        }catch (IOException e){

        }
    }

7、String存储结构变更

以前底层是使用char[]数组,jdk9改为字节数组byte[]。(一个字符等于两字节等于16bit)
原因:大多数字符串对象包含的仅仅是拉丁字符(abcd/拼音文字等都属于拉丁字符),而事实上这些拉丁字符仅仅需要一个字节就能存储了,因此,如果使用char数组存储拉丁字符,会浪费一半的空间。

问题:中文是两个字节,一个byte是存不下的,怎么解决?
coder变量,coder代表编码的格式,目前String支持两种编码格式LATIN1UTF16
LATIN1需要用一个字节来存储。而UTF16需要使用2个字节或者4个字节来存储。

注意:StringBuilder与StringBuffer也是更着改变了,底层也是用的byte[]

8、统一的jvm日志系统

二、JDK11

安装jdk11

IDEA切换到JDK11

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、Jshell(java9开始)

启动jshell就相当于进入 main方法,直接敲代码执行就可以了。
简而言之,使用 JShell,你可以输入代码片段并马上看到运行结果,然后就可以根据需要作出调整

C:\Users\Administrator>jshell
|  Welcome to JShell -- Version 11.0.1
|  For an introduction type: /help intro

jshell> System.out.print("asd");
asd
jshell> int n=200;
n ==> 200

jshell> System.out.print(n);
200

好处是可以使我们快速的调试测试代码,而不用去新建一个class文件,在new一个类,在写一个main方法,编译再运行。

/help可以查看一些命令,包括如何退出jshell等。/exit
/import可以查看默认导入的包,也可以直接导import 包;
/可以查看常用的指令

从外部加载源代码:

/open E:\HelloWorld.java

2、Dynamic Class-File Constants类文件新添的一种结构

  • Java的类型文件格式将被拓展,支持一种新的常量池格式:CONSTANT_Dynamic,加载CONSTANT_Dynamic会将创建委托给bootstrap方法。
  • 目标:是降低开发新形式的可实现类文件约束带来的成本和干扰。

3、局部变量类型推断(var “关键字”)

  • var是语法的一个改进,但它不是关键字。
  • 局部变量类型推断就是左边的类型直接使用 var 定义,而不用写具体的类型,编译器能根据右边的表达式自动推断类型。
jshell> var b=new StringBuilder("123");
b ==> 123

jshell> System.out.print(b.getClass());
class java.lang.StringBuilder

注意点:
1、var a;这样不可以,因为无法推断
2、类的属性的数据类型不可以使用var

主要用途,用在lambda表达式中,在声明隐式类型的lambda表达式的形参时允许使用var,使用var的好处是在使用lambda表达式时给参数加上注解
(@Deprecated var x, @Nullable var y) -> x.process(y);

4、新加一些实用的API

4.1、创建只读集合of【jdk9就有】

自 Java 9 开始,Jdk 里面为集合(List/ Set/ Map)都添加了 of 和 copyOf 方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。

        //快速创建不可改变集合
        List<String> list1 = List.of("1", "2", "3");
        System.out.println(list1);
        //不能添加元素 Exception in thread "main" java.lang.UnsupportedOperationException
//        list1.add("4");

        List<String> list2 = Arrays.asList("1", "10");
        System.out.println(list2);
        //不能添加元素 Exception in thread "main" java.lang.UnsupportedOperationException
        list2.add("100");
        System.out.println(list2);

LIST.OF和ARRAYS.ASLIST区别:

  • Arrays.asList返回可变的list,而List.of返回的是不可变的list,前者可以通过set方法修改,后者不行
  • Arrays.asList支持null,而List.of不行
  • Arrays.asList:数组的修改会影响原数组。

4.2、集合copyOf

示例1//使用of创建的集合是不可变类型的集合
var list = List.of("Java", "Python", "C");
var copy = List.copyOf(list);
System.out.println(list == copy); // true

示例2:
var list = new ArrayList<String>();
var copy = List.copyOf(list);
System.out.println(list == copy); // false

示例1和2代码差不多,为什么一个为true,一个为false?
copyOf 方法会先判断来源集合是不是 AbstractImmutableList 类型的,如果是,就直接返回,如果不是,则调用of创建一个新的集合。

使用ofcopyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报 java.lang.UnsupportedOperationException 异常。

上面演示了 ListofcopyOf 方法,SetMap 接口都有。

4.3、增强Stream API【jdk9就有了】

1、ofNullable
允许传入null创建一个stream对象。
Stream.of()是不允许传入null来创建stream对象的。

public static void main(String[] args) {
   Stream<String> stream1 = Stream.of("a", "b", "c");
   stream1.forEach(System.out::println);
   System.out.println("------------------------------");
   Stream<String> stream2 = Stream.of();//流中没有数据
   stream2.forEach(System.out::println);
   System.out.println("------------------------------");
   //java.lang.NullPointerException  因为传入的null会被解析成一个数组对象,这个对象会进一步访问它的长度
//        Stream<String> stream3 = Stream.of(null);
//        stream3.forEach(System.out::println);
   //可以传入一个null来创建流对象
   Stream<Object> objectStream = Stream.ofNullable(null);
   objectStream.forEach(System.out::println);
}

2、takeWhile
从流中获取判定器为真的元素,一旦遇到元素为假,就终止处理

public static void main(String[] args) {
    Stream<Integer> stream1 = Stream.of(1,3,4,5,6);
    //从流中获取判定器为真的元素,一旦遇到元素为假,就终止处理
    Stream<Integer> integerStream = stream1.takeWhile(t -> t % 2 != 0);
    integerStream.forEach(System.out::println);
}
1
3

3、dropWhile
从Stream中依次删除满足条件的元素,直到不满足条件为止结束删除

stream1 = Stream.of(1,3,4,5,6);
Stream<Integer> integerStream1 = stream1.dropWhile(t -> t % 2 != 0);
integerStream1.forEach(System.out::println);
4
5
6

4、流的迭代

//流的迭代,创建流
Stream<Integer> iterate = Stream.iterate(1, t -> (2 * t) + 1);
iterate.limit(10).forEach(System.out::println);
System.out.println("==============================================");
//有限的迭代,类似for循环
Stream<Integer> iterate1 = Stream.iterate(1, t -> t < 1000, t -> (2 * t) + 1);
iterate1.forEach(System.out::println);

4.4、新增的字符串API

判断字符串是否为空白:isBlank

String s="   ";
System.out.println(s.isBlank());
String s1="   \n \r \t ";
System.out.println(s1.isBlank());

true
true

去除首尾空白:
strip:去除字符串首尾的空白,包括英文和其他所有语言中的空白字符
stripLeading:去除字符串首部的空白
stripTrailing:去除字符串尾部的空白
trim:去除字符串首尾的空白字符,只能去除码值小于等于32的空白字符

String s2=" asd ";
System.out.println(s2.strip());

String s3="\r \t asd \n";
System.out.println(s3.strip());

复制字符串:

String str="java";
String repeat = str.repeat(5);
System.out.println(repeat);
javajavajavajavajava

行数统计:

String line="A\nB\n";
long count = line.lines().count();
System.out.println(count);

4.5、String行数统计的应用

以前读取一个文件的内容,需要使用转换流和缓冲流

StringBuffer buffer = new StringBuffer();
String line; // 用来保存每行读取的内容
BufferedReader bufferreader = new BufferedReader(new InputStreamReader(new FileInputStream("src\\main\\java\\com\\example\\springboot\\aoptest\\jdk11\\StringTest.java")));
line = bufferreader.readLine(); // 读取第一行
while (line != null) { // 如果 line 为空说明读完了
    buffer.append(line); // 将读到的内容添加到 buffer 中
	buffer.append("\n"); // 添加换行符
    line = bufferreader.readLine(); // 读取下一行
}
//buffer中的内容写出来
bufferreader.close();
System.out.println(buffer) ;

现在使用String新API:
将文件中的内容直接全部放到一个String中,然后使用流,对字符串进行行的提取,就可以快速的读取文件中的内容了。
可以省略转换流和缓存流,完全可以替代BufferReader,更加的方便和好用

FileInputStream fis = new FileInputStream("src\\main\\java\\com\\example\\springboot\\aoptest\\jdk11\\StringTest.java");
//available方法可以在读写操作前先得知数据流里有多少个字节可以读取
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();//关闭流

//把内容一次性读到String中
String line=new String(buffer);
//一共有几行,lines返回从此字符串中提取的行的流,由行终止符分隔。
long count = line.lines().count();
System.out.println(count);
//遍历每一行
line.lines().forEach(System.out::println);

4.6、optional增强

//of:方法中如果传入null,会抛出空指针异常
//ofNullable:可以兼容空指针
//orElse:如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)
Object abc = Optional.ofNullable("123").orElse("abc");
System.out.println(abc);
//orElseThrow
Object object1 = Optional.ofNullable(null).orElseThrow(()->new RuntimeException("xxx不能为空"));
System.out.println(object1);

4.7、InputStream 加强

transferTo,可以用来将数据直接传输到 OutputStream,这是在处理原始数据流时非常常见的一种用法。
例如:
文件复制

public static void main(String[] args) throws IOException {
	//流会自动关闭
    try(var is = new FileInputStream("src\\main\\java\\com\\example\\springboot\\aoptest\\jdk11\\file");
        var os=new FileOutputStream("file2");
    ){
        //把输入流中的所有数据直接自动地复制到输出流中
        is.transferTo(os);
    }
}

非常实用的方法,不需要在写一个循环,也不需要写一个缓冲区。

5、标准java异步HTTP客户端【jdk9开始引入】

以前使用apachehttpclient:

public static void main(String[] args) {
     //apache的httpclient
     String url="http://localhost:8080/aopController?id=1&name=lzj";
     String result = httpGet(url);
     System.out.println(result);
 }
 //httpGet
 private static String httpGet(String url) {
     // get请求返回结果
     String parse = null;
     // 创建httpclient对象
     CloseableHttpClient client = HttpClients.createDefault();
     // 创建get方式请求对象
     HttpGet request = new HttpGet(url);
     try {
         // 设置通用的请求属性,设置header信息
         request.addHeader("content-type", "application/json");
         // 获取相应数据,这里可以获取相应的数据
         HttpResponse response = client.execute(request);

         // 判断网络请求是否成功,成功的状态码200
         if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
             // 读取服务器返回过来的json字符串数据
             HttpEntity entity = response.getEntity();
             parse = EntityUtils.toString(entity, "utf-8");
         } else {
             throw new RuntimeException("xxx接口失败!!");
         }
     } catch (IOException e) {
         throw new RuntimeException(e);
     } finally {
         //释放连接
         request.releaseConnection();
     }
     return parse;
 }

JDKHttpClient(jdk11)
java.net.http.HttpClient 是 jdk11 中正式启用的一个 http 工具类(其实早在 jdk9 的时候就已经存在了,只是处于孵化期),官方想要取代 HttpURLConnectionApache HttpClient 等比较古老的开发工具。

    public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
        //newHttpClient:返回一个默认设置的HttpClient
        HttpClient httpClient = HttpClient.newHttpClient();
        //如果想要自定义设置使用newBuilder
//        HttpClient httpClient1 = HttpClient.newBuilder()
//                .version(HttpClient.Version.HTTP_2)//http 协议版本 1.1 或者 2
//                .connectTimeout(Duration.ofMillis(5000))//连接超时时间,单位为毫秒
//                .followRedirects(HttpClient.Redirect.NEVER)//连接完成之后的转发策略
//                .executor(Executors.newSingleThreadExecutor())//指定线程池
//                //认证,默认情况下 Authenticator.getDefault() 是 null 值,会报错
//                //.authenticator(Authenticator.getDefault())
//                //代理地址
//                //.proxy(ProxySelector.of(new InetSocketAddress("http://www.baidu.com", 8080)))
//                //缓存,默认情况下 CookieHandler.getDefault() 是 null 值,会报错
//                //.cookieHandler(CookieHandler.getDefault())
//                .build();//创建完成
        //HttpRequest 是发起请求的主体配置
        HttpRequest request = HttpRequest.newBuilder()
                //存入消息头
                //消息头是保存在一个TreeMap里的
                .header("Content-Type", "application/json")
                .version(HttpClient.Version.HTTP_2)//http 协议版本
                //url地址,也可以直接在newBuilder()中设置
                .uri(URI.create("http://localhost:8080/aopController?id=1&name=lzj"))
                //超时时间
                .timeout(Duration.ofMillis(5000))
                //发起一个 post 消息,需要存入一个消息体
                //.POST(HttpRequest.BodyPublishers.ofString("hello"))
                //发起一个 get 消息,get 不需要消息体
                .GET()
                .build();
        //同步方式发起请求
//        HttpResponse<String> response =  httpClient.send(request, BodyHandlers.ofString());
        //异步方式发起请求
        CompletableFuture<HttpResponse<String>> httpResponseCompletableFuture = httpClient.sendAsync(request, BodyHandlers.ofString());
        HttpResponse<String> response = httpResponseCompletableFuture.get();

        System.out.println(response.body());
    }

6、移除的一些其他内容

移除项:

移除了com.sun.awt.AWTUtilities
移除了sun.misc.Unsafe.defineClass,
使用java.lang.invoke.MethodHandles.Lookup.defineClass来替代
移除了Thread.destroy()以及 Thread.stop(Throwable)方法
移除了sun.nio.ch.disableSystemWideOverlappingFileLockCheck、sun.locale.formatasdefault属性
移除了jdk.snmp模块
移除了javafx,openjdk估计是从java10版本就移除了,oracle jdk10还尚未移除javafx,而java11版本则oracle的jdk版本也移除了javafx
移除了Java Mission Control,从JDK中移除之后,需要自己单独下载
移除了这些Root Certificates :Baltimore Cybertrust Code Signing CA,SECOM ,AOL and Swisscom

废弃项:

-XX+AggressiveOpts选项
-XX:+UnlockCommercialFeatures
-XX:+LogCommercialFeatures选项也不再需要

7、更简化的编译运行程序【jdk9引入】

以前编译运行程序,需要先javac编译,然后再用命令java才能运行程序。
现在直接使用java就行

public class HelloJava{
	public static void main(String[] args){
		System.out.println("hello");
	}
}
G:\Desktop\新建文本文档>java HelloJava.java
hello

注意点 :
1)执行源文件中的第一个类, 第一个类必须包含主方法
2)并且不可以使用别源文件中的自定义类, 本文件中的自定义类是可以使用的.

8、Epsilon垃圾收集器【实验性质的】

A NoOp Garbage Collector:一个没操作的垃圾收集器。

JDK上对这个特性的描述是: 开发一个处理内存分配(可以创建对象),但不实现任何实际内存回收机制的GC, 一旦可用堆内存用完, JVM就会退出。

如果有System.gc()调用, 实际上什么也不会发生(这种场景下和-XX:+DisableExplicitGC效果一样), 因为没有内存回收, 这个实现可能会警告用户尝试强制GC是徒劳.

用法 : -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

jvm参数:-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
class Garbage {
	int n = (int)(Math.random() * 100);
	//这个方法是GC在第一次清除当前对象时,会调用一次,只调用一次
	@Override
	public void finalize() {
		System.out.println(this + " : " + n + " is dying");
	}
}
public class EpsilonTest {
	public static void main(String[] args) {
		boolean flag = true;
		List<Garbage> list = new ArrayList<>();
		long count = 0;
		while (flag) {
			list.add(new Garbage());
			if (list.size() == 1000000 && count == 0) {
				list.clear();
				count++;
			}
		}
		System.out.println("程序结束");
	}
}
结果:不会进行垃圾回收,内存用完,直接使程序停止
Terminating due to java.lang.OutOfMemoryError: Java heap space

使用这个选项的原因 :
提供完全被动的GC实现, 具有有限的分配限制和尽可能低的延迟开销,但代价是内存占用和内存吞吐量.

主要用途如下 :

  • 性能测试(它可以帮助过滤掉GC引起的性能假象)
  • 内存压力测试(例如,知道测试用例 应该分配不超过1GB的内存, 我们可以使用-Xmx1g –XX:+UseEpsilonGC,如果程序有问题, 则程序会崩溃,比如:内存泄漏)
  • 非常短的JOB任务(对象这种任务, 接受GC清理堆那都是浪费空间)
  • VM接口测试
  • Last-drop 延迟&吞吐改进

9、ZGC,重要【实验性质的,不建议用到生产环境】

ZGC:一个短延迟的垃圾回收器。jdk11windows版不支持ZGClinux下才能使用

  • GC暂停时间不会超过10ms
  • 既能处理几百兆的小堆, 也能处理几个T的大堆(OMG)
  • G1相比, 应用吞吐能力不会下降超过15%
  • 为未来的GC功能和利用colord指针以及Load barriers优化奠定基础
  • 初始只支持64位系统

ZGC的设计目标是:支持TB级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于15%。 将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存),或压缩堆。

ZGC是一个并发, 基于region, 压缩型的垃圾收集器, 只有root扫描阶段会STW, 因此,GC停顿时间不会随着堆的增长和存活对象的增长而变长.

ZGC与G1的停顿时间对比:
ZGC : avg 1.091ms max:1.681
G1 : avg 156.806 max:543.846

用法 : -XX:+UnlockExperimentalVMOptions –XX:+UseZGC

9.1、ZGC的工作原理

为了实现其目标,ZGCHotspot Garbage Collectors增加了两种新技术:着色指针和读屏障

着色指针

32位的jdk用不到TB级内存容量,只能用到最多4G。
64位系统是使用8字节,来作为内存编址,因此,数据量是很大的,可支持的内存也会变的非常的大,远远大于TB级,保存引用的数据量由4个字节扩展到8字节,多出来的数据,就会给我们无限的可能,前四个字节4G,稍微往后,高位用上一点点,那么内存范围就会变化很大

着色指针是一种将信息存储在指针(或使用Java术语引用)中的技术。
因为在64位平台上(ZGC仅支持64位平台),指针可以处理更多的内存,因此可以使用一些位来存储状态。

https://blog.csdn.net/hejuecan5759/article/details/106390994/
https://www.cnblogs.com/fiftyonesteps/p/12568737.html

10、完全支持Linux容器(包括Docker)

许多运行在Java虚拟机中的应用程序(包括Apache Spark和Kafka等数据服务以及传统的企业应用程序)都可以在Docker容器中运行。但是在Docker容器中运行Java应用程序一直存在一个问题,那就是在容器中运行JVM程序在设置内存大小和CPU使用率后,会导致应用程序的性能下降。这是因为Java应用程序没有意识到它正在容器中运行。随着Java 10的发布,这个问题总算得以解决,JVM现在可以识别由容器控制组(cgroups)设置的约束。

如何适应docker,这些都是自动完成的。

11、支持G1上的并行完全垃圾收集

对于 G1,相比于 JDK 8,升级到 JDK 11 即可免费享受到:并行的Full GC,快速的CardTable 扫描,自适应的堆占用比例调整(IHOP),在并发标记阶段的类型卸载等等。这些都是针对G1 的不断增强,其中串行Full GC 等甚至是曾经被广泛诟病的短板,你会发现GC配置和调优在 JDK11 中越来越方便。

12、Java Flight Recorder(JFR)

Flight Recorder源自飞机的黑盒子,会把jvm运行的细节全部记录下来,最终记录到一个文件中,通过分析文件,能够知道jvm内部是怎么运作的,比如:GC怎么工作的,类什么时候加载,对象什么时候创建等等。

Flight Recorder以前是商业版的特性,在java11当中开源出来,它可以导出事件到文件中,之后可以用Java Mission Control来分析。可以在应用启动时配置java -XX:StartFlightRecording,或者在应用启动之后,使用jcmd来录制,比如

$ jcmd <pid> JFR.start
$ jcmd <pid> JFR.dump filename=recording.jfr
$ jcmd <pid> JFR.stop

JFR 是一套集成进入 JDK、JVM 内部的事件机制框架,通过良好架构和设计的框架,硬件层面的极致优化,生产环境的广泛验证,它可以做到极致的可靠和低开销。在 SPECjbb2015 等基准测试中,JFR 的性能开销最大不超过 1%,所以,工程师可以基本没有心理负担地在大规模分布式的生产系统使用,这意味着,我们既可以随时主动开启 JFR 进行特定诊断,也可以让系统长期运行 JFR,用以在复杂环境中进行“After-the-fact”分析。还需要苦恼重现随机问题吗?JFR 让问题简化了很多。

使用:

//找出java进程
G:\Desktop\资料\学习资料\jdk11新特性\笔记源码\code>jps -l
8592
10740 org.jetbrains.idea.maven.server.RemoteMavenServer
11044 org.jetbrains.jps.cmdline.Launcher
9236 jdk.jcmd/sun.tools.jps.Jps
9528 JFRTest
//打开jfr
G:\Desktop\资料\学习资料\jdk11新特性\笔记源码\code>jcmd 9528 JFR.start
9528:
Started recording 1. No limit specified, using maxsize=250MB as default.

Use jcmd 9528 JFR.dump name=1 filename=FILEPATH to copy recording data to file.

//把数据导出来
G:\Desktop\资料\学习资料\jdk11新特性\笔记源码\code>jcmd 9528 JFR.dump filename=test.jfr name=1
9528:
Dumped recording "1", 300.0 kB written to:
G:\Desktop\资料\学习资料\jdk11新特性\笔记源码\code\test.jfr

//停止jfr
G:\Desktop\资料\学习资料\jdk11新特性\笔记源码\code>jcmd 9528 JFR.stop name=1
9528:
Stopped recording "1".

查看导出来的jfr文件:jdk11没有提供jfr命令查看,jdk12以上才提供。

JDK11JDK9是Java Development Kit (JDK)的不同版本。JDK11是较新的版本,而JDK9是稍旧的版本。它们之间有一些区别和更新。在JDK11中,一些主要的特性包括模块化系统、Jshell、多版本兼容jar包、接口中定义私有方法等。而在JDK9中也有一些特性,例如标准java异步HTTP客户端、更简化的编译运行程序、Epsilon垃圾收集器等。此外,JDK11还包含了一些新的API和改进,如动态的Class-File Constants类文件、局部变量类型推断、增强的Stream API等。关于JDK11JDK9的具体差异和特性,您可以根据需要选择合适的版本进行安装和使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JDK11安装包,JDK11安装包](https://download.csdn.net/download/qq_45748838/86264351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [jdk9和jdk11](https://blog.csdn.net/weixin_42412601/article/details/110728812)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [java-jdk11版本jar包下载](https://download.csdn.net/download/weixin_42593797/88217226)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值