ZGC
Java 11开始, 引入了一个新的实验性质的垃圾收集器 Z Garbage Collector. 它能处理几 GB 到几 TB 的 heap, 保证 stop the world 的时间不超过10ms, 并且这个时间不随着 heap 的大小而增加.
Java 11开始, 引入了一个新的实验性质的垃圾收集器 Z Garbage Collector. 它能处理几 GB 到几 TB 的 heap, 保证 stop the world 的时间不超过10ms, 并且这个时间不随着 heap 的大小而增加.
Java 是在 VM 里面运行的语言, 同时要做到平台无关性, 所以它有自己的 debug 接口和实现.
官方关于 JPDA 的链接: https://docs.oracle.com/javase/6/docs/technotes/guides/jpda/
上面的图很容易理解, VM 具体实现和 backend 接口直接使用 JVM TI 来作为通信接口.
Debugger 和 Debuggee 之间定义了协议: JDWP (这类似于 HTTP).
Debugger 自己的和后端通信以及自己的 UI 使用 JDI(这类似与 HTML)
如何远程 debug:
从 Java 9 开始:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:8000 myApp
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000 myApp
Java 9 之前:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 OurApplication
Java 5 之前:
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 myApp
参数列表:
a list of options:
客户端最简陋的可以使用 jdk 自带 jdb.
更多信息参考: https://www.baeldung.com/java-application-remote-debugging
有关 jar 文件
解压 jar 文件:
jar xvf xxx.jar
unzip xxx.jar -d ./directoryToExtractTo
jar tf jar-file # 仅仅查看文件//使用 jar 命令只能解压到当前目录
压缩为 jar 文件:
jar cvf xxx.jar .
jar cf jar-file input-file(s)如果是使用 Spring boot big jar 的方式, 要制定 manifest 文件
jar cfm xxx.jar Manifest.txt MyPackage/*.class
jar cmf jar-file existing-manifest input-file(s)更新 jar 文件 使用 input-file(s) 添加或更新 jar 里面的文件
jar uf jar-file input-file(s)
# 只更新 my.jar 里的这个文件
jar -uf my.jar BOOT-INF/classes/application-Production.properties more info:
jar (Java™ Archive) 文件格式是 Java 提供的压缩方式, 和 zip 使用的格式是一样的. 不过里面添加了一些其他特性, 比如使用 MANIFEST.MF 添加了扩展机制, 使使用者能够更方便的扩展.
围绕这个图, 做几点解说(左边的虚线框表示 Tomcat):
SYN backlog 长度由 /proc/sys/net/ipv4/tcp_max_syn_backlog 设置, 还有文章说最终值有几个因素共同决定, 不过在 Linux Kernel 4.3 之后,这个 syn backlog 不在由 net.ipv4.tcp_max_syn_backlog 决定, 而是由 net.core.somaxconn 决定
eric@host:~$ sysctl net.core.somaxconn
net.core.somaxconn = 4096
eric@host:~$ sysctl net.ipv4.tcp_max_syn_backlog
net.ipv4.tcp_max_syn_backlog = 4096如何查看一个监听端口的 SYN backlog 当前的队列长度?
没有直接看当前长度的命令, 不过可以自己手工计算:
# 查看连到当前 host 8080 端口上并且处于 sync-recv 状态的连接
eric@host:~$ ss -n state syn-recv sport = :8080
参考: https://blog.cloudflare.com/syn-packet-handling-in-the-wild/
在 Java NIO 和 NIO2 里面我们经常看到attach 和 attachment 相关的 API, 如:
Objcet SelectionKey.attch(Object obj)
Object SelectionKey.attachment()
SelectionKey AbstractSelector.register(AbstractSelectableChannel ch,int ops, Object att);
这里的 Attachment 是一个 Object 对象, 也就是说它可以 attach 任何对象, 为什么要 attach 一个对象呢?
我们从 Blocking IO 说起, 当 Blocking IO 的时候, 读字节流或字符流的的线程一直 block 在读操作上, 不去干其它事情, 当来一个字节/字符的时候, 它就读一个, 直到返回 -1 代表读完(EOF). 可是当时 NIO 的时候, 读线程直接返回, 是由一个专门的 IO 线程操作 Selector 去读取的, 当有部分数据到达的时候, 它就帮你读取, 读完来的数据之后, 还没读取到 EOF, 那么要继续监听这个 socket, 再次等待它接下来的数据, 那么刚才读取的数据放哪里呢? 之后来的数据怎么拼接到原来的数据之后呢? 那么就需要有一个容器放置还没有读完的半成品, 在下次同一个 socket 来数据的时候, 再次拿出这个容器, 继续放数据, 那么这个容器怎么可以容易的每次都有数据的时候拿到呢? 那就放到 SelectionKey 上面吧, 反正每次都是通过 Selectionkey 知道有数据的, 一旦 SelectionKey 有数据, 就通过它拿到之前装有半成品的容器, 那么可以继续放了.
每次读完通过 attach(Object) 方法附在上面, 下次当有数据来的时候, 通过 attachment 方法拿到之前的容器.