综合/最新
Java编程专题、Nginx Jetty HTTP C/S、Java Web/Network、Android应用开发、JDK源码、Gradle构建
Javadoc、Quarkus原生AOT
新:
  JDK25+预览 - PEMDecoder.of().decode(pemString);
原则 - 主用JDK版本选择安装版,备用JDK则用压缩版。
JDK/JRE:
  Java/JDK版本重大变化:
    新 - JSpecify @NonNull 标准化 https://openjdk.org/jeps/8303099
    Java 25+ 支持模块儿导入 import module java.sql; 紧凑对象头(省内存) -XX:+UseCompactObjectHeaders
    Java 18+ 默认编码统一为 StandardCharsets.UTF_8
    Java 9+  引入了JPMS(Java Platform Module System)
  Java程序部署运行实战:
    Java Virtual Machine 首选 Oracle 的 HotSpot,其他则有 J9 等。
    源码编译用javac命令,最终运行用java,常见的加参数调优通常指后者。
    实验性选项启用(更精确时钟等):java -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps App
    低延迟实时场景(游戏等) java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
    JVM参数查看  java -XX:+PrintFlagsFinal -version
      jinfo -flags 
    [通用]生产用JVM参数
      -XX:MaxRAMPercentage=95 -XX:+UseZGC -XX:+UseCompactObjectHeaders
      说明 - 最大内存百分比默认值为过于保守的25%(等同-Xmx初始值),故改为95%来充分利用;推荐值为75%,会被显式参数-Xmx1024m覆盖。
        启用更好的ZGC垃圾回收器。
    [容器]生产用JVM参数
      ... -XX:+ExitOnOutOfMemoryError
      说明 - OOM抛异常但可能不会退出JVM;为了Docker能感知到,进而触发容器自动重启,应在内存不足时就使其JVM强退。
    [非容器]生产用JVM参数
      ... -XX:+CrashOnOutOfMemoryError
      说明 - 为了Docker能感知到,进而触发容器自动重启,应在内存不足时就使其Crash强退JVM,且输出hs_err_pid123.log文件(比*.hprof轻量很多)。
        如果程序很重要,可在OOM时换为通过脚本或Systemd来重启 -XX:OnOutOfMemoryError=/script/use-systemd-restart.sh
    [非容器]开发用JVM参数
      ... -XX:+HeapDumpOnOutOfMemoryError
      说明 - OOM时让JVM在程序当前目录生成排查信息,生成时资源消耗过大,应只用在重现阶段,可加个 -XX:HeapDumpPath=/tmp/hd.hprof 来指定路径。
    JVM优雅退出 - https://www.bilibili.com/opus/679791639661641744
  JDK/JRE 完全版:
    Java/JDK下载地址
    Linux安装:apt install default-jre  (Debian默认为JDK21) 或用解压缩方式:
      wget https://download.oracle.com/java/24/latest/jdk-24_linux-aarch64_bin.tar.gz  或 jdk-24_linux-x64_bin.tar.gz
      tar -xf jdk-24_linux-*64_bin.tar.gz
  JRE 自定义镜像:
    cd "C:\Program Files\Java\jdk-24\bin"
    ./jlink --help  只含 java.base 则生成后约 30-47MiB。
    [可选] 查看依赖的modules: jdeps HelloWorld.class
    不含应用: ./jlink --output $HOME/Desktop/my-jre/ --add-modules java.base
        ./jlink --output $HOME/Desktop/my-jre/ --add-modules java.base,jdk.localedata --include-locales en,zh-Hans-CN --strip-debug --compress=zip-9
        说明 - 不指定 --module-path 则默认取 JDK 目录 jmods/;可指定 jar(不指定模块名则取文件名) 和通过 jar 或 *.class 生成的 jmod 文件。
          其中 --strip-debug --compress=zip-9 参数均为可选,但建议加上,压缩似乎只针对 my-jre/lib/modules 文件。
    包含应用: ./jlink --output $HOME/Desktop/my-jre/ --module-path ../jmods/:path/to/your-modular.jar:your-modular.jmod --add-modules java.base
        说明 - 运行命令 java --module your.modular/HelloWorld.class
    其他参数:如果想重用参数,可通过配置文件指定 ./jlink @my.conf
        --add-modules java.base,javafx.base,javafx.graphics,javafx.controls --launcher start=java.base/java
        指定本地化语言(默认en_US) ./jlink --add-modules java.base,jdk.localedata --include-locales en,ja,zh-Hans-CN
    清理输出目录: rm -r $HOME/Desktop/my-jre/
    [可选] 创建jmod文件: jmod create --class-path mods/com.example.mymodule --output mymods/com.example.mymodule.jmod --module-version 1.0.0 --main-class com.example.mymodule.MyClass --resource-path resources
新:
  Oracle GraalVM 仅支持 CycloneDX 生成 SBOM,暂不支持 SPDX 格式。
  不可变字段懒加载/按需延迟赋值 final StableValue sv = StableValue.of();sv.orElseSet(() -> X.create());
  JDK 24+:
    支持 ASM 能力 java.lang.classfile.ClassFile.of().parse(byte[] bytes)
    通过预缓存加快启动速度 java -XX:AOTCache=app.aot -jar app.jar
    通过--enable-linkable-runtime减少JDK镜像尺寸,从JDK_HOME\jmods\抽取所用classes。
  Stream.of(1, 2, 3).gather(Gatherers.mapConcurrent(3, (item) -> {
    return item * item; // Thread.currentThread().isVirtual()
  })).toList(); // map 未使用 VirtualThread;JDK 24+ 首选 mapConcurrent
死记、偏门:
  常量 - 编码方式 StandardCharsets.UTF_8、换行符 System.linSeparator()、本机地址 InetAddress.getLocalHost().getHostAddress()
    遍历系统环境变量 System.getenv().entrySet().stream().forEach(System.out::println);
  IO/URL - 当前目录 System.getProperty("user.dir") 在MAC DOCK上启动则总为“/”,Windows正常; Path对象不含结尾的斜杠。
    File.createTempFile("x".repeat(3), ".txt") 返回 File,而 Files.createTempFile(...) 则返回 Path。
    URI格式不允许存在反斜杠和空格:URI.create("file://C:\\d.txt".replaceAll("\\\\", "/").replaceAll(" ", "%20"); // or new URL(已过时);
  其他 - Gradle判断>=Java版本:org.gradle.api.JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17); 也可用Guava库com.google.common.base.JavaVersion
  国名代码 - Locale.getISOCountries(); // 输出2字母大写,等同域名后缀,3字母则更清晰;全名用 locale.getDisplayCountry(Locale.ENGLISH)
  时区 - PRC or CTT 即 China Standard Time 上海时区,简短易记。
    TimeZone.getTimeZone("PRC").toZoneId();
    ZoneId.SHORT_IDS.get("CTT"); // 输出 Asia/Shanghai
    ZoneId.of("Asia/Shanghai"); // 完整写法
    ZoneOffset.UTC.normalized() // 规范化
  字符串拼接首选线程安全的: var sb = new StringBuffer(); sb.append(request.getProtocol()); sb.toString();
  无法跳读,直接获取最后一个元素,仍然会接收之前所有元素文件流 - request.getParts().stream().findLast().getInputStream();
  时间 - 周年份(Week Year)指跨年周的天数低于4天就归属到新年份了,1月1日永远属于新年份第一周。Java中用YYYY表示周年份,常规年份使用yyyy。
  错误响应标准(RFC 9457) - org.springframework.http.ProblemDetail
  NetBeans控制台中文乱码解决(macOS无此问题):计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage 将 ACP 值改为 65001。
IDE:
  NetBeans - 
    图标写死了JDK目录:"C:\netbeans64.exe" --jdkhome "C:\Program Files\Apache NetBeans\jdk"
    离线模式 NetBeans -> Tools -> Options -> Java -> Gradle -> ✔Offline
    macOS安装包为Apache-NetBeans-25.pkg。
    v25 Bug - 时间久了,外部复制后粘贴到编辑器里失效。
    Git -> Show Changes 为空但项目图标上有变动(估计把staged也算为了变动)图标,可通过 git status 查看并修复 git restore --staged x/src/main/java/pkg/name/X.java;若存在转义 x/src/main/resources/[\346\234\252\344\275\277\347\224\250].xhtml,可通过x/src/main/resources/*.xhtml 通配掉。