Java

浏览该分类下的所有文章

Project Leyden如何用AOT Cache 加速Java冷启动

Java 在峰值吞吐上很强,但类加载、链接、方法画像与 JIT 预热,让冷启动成为容器扩容和短任务的隐性成本。Project Leyden 没有抛弃 JVM,而是通过训练运行生成 AOT Cache,把部分启动与预热工作提前完成。本文梳理 JDK 24、25、26 的演进,分析其与 GraalVM Native Image 的差异,并给出生成命令、CI/CD 流程、诊断参数与常见失效场景,帮助你判断哪些 Java 服务值得使用 Leyden,并确认缓存在生产环境真正生效。

全局失效、单点注销与登录防护实践

本文围绕 JWT 在实际项目中的安全短板展开,分析了“无法主动撤销 Token、改密后旧 Token 仍有效、管理员降权失效、登录接口易被爆破”等常见问题,并给出一套工程化解决方案。通过 `authVersion` 实现账号级 Token 全局失效,通过 Redis + SHA-256 黑名单实现单设备注销,通过 Lua 脚本完成账号与 IP 双维度限流,再结合过滤器分层校验,实现从签发、验证到撤销的完整安全闭环。文章同时讨论了 Redis TTL、分布式锁、Redis Cluster hash tag、密钥强校验等细节,展示如何在保留 JWT 无状态优势的同时,补齐其安全缺陷,构建一套可靠的认证体系。

Java项目该如何选择8.4LTS与9.7LTS

MySQL 8.0 已于 2026 年 4 月正式进入 EOL,大量仍运行在 8.0 上的 Java 项目需要重新规划数据库版本。与此同时,MySQL 9.7 已成为新的 LTS,因此升级问题不再只是“8.4 还是 9.x”。本文结合官方升级路径,从 MySQL 8.4 与 9.7 的选择、认证插件变化、Connector/J、TLS、Upgrade Checker、SQL 回归、备份和回滚等方面,给出一套适用于 Spring Boot 项目的实际迁移方案。对于存量系统,更稳妥的策略通常是先迁移到 8.4 LTS,在稳定运行后再根据生命周期决定是否继续升级 9.7 LTS。

2026年值得关注的7个技术变化

2026 年,Java 生态正在迎来新一轮技术升级。从 JDK 26 原生支持 HTTP/3、Virtual Thread 与 Structured Concurrency,到 Project Leyden 推进 AOT Cache,再到 JDK 27 在对象头压缩、垃圾回收、后量子安全和 JFR 脱敏方面的增强,JVM 正变得更高效、更安全。同时,Spring Boot 4.1 加强 gRPC、OpenTelemetry 等生产能力,Spring AI 2.0 则通过 Tool Calling、MCP 和 Agent 将 Java 深度带入 AI 时代。本文系统梳理 2026 年 Java 值得关注的核心技术变化,并给出新项目的技术选型思路。

JDK27如何用Compact Object Headers压缩整个堆

Java应用的内存浪费不只来自业务字段,每个对象携带的对象头也会在海量实例下形成开销。本文围绕JDK 27默认启用的Compact Object Headers,拆解传统与紧凑对象头的布局差异,解释少4字节为何影响堆占用、GC频率、缓存局部性和容器密度,并通过JOL展示变化。同时给出JDK 25、26的启用方式、灰度流程、监控指标、适用场景与风险边界,帮助团队在升级前完成可验证、可回滚的内存优化。

一个IP查询接口,暴露出的系统设计边界

文章围绕核心数据与增强数据的边界划分,讨论失败降级、超时控制、异步补偿、可信代理解析、私有地址处理以及本地 IP 库迁移检查等关键问题。通过统一“IP未知”状态,让系统在定位服务不可用时仍保持评论提交能力,同时保留内部监控和问题排查能力。最终实现一个可失败、可恢复、可观测的外部数据增强方案。

一次OOM排查实录

日志在运行时被硬截断,排查后发现是 Linux OOM Killer 将进程强制 kill,根因是 2 GB 服务器同时运行 3 个未限制堆大小的 Spring Boot 项目、MySQL 8.0 和监控组件,JVM 默认占用近 3 GB,MySQL 参数又消耗数百 MB,且没有 Swap 作为缓冲。通过为每个 JVM 设置‑Xms/‑Xmx(如 512 M、256 M),调小 MySQL 的 innodb_buffer_pool、max_connections、关闭 performance_schema 并添加 2 GB swap,内存使用降至安全范围,进程不再被 OOM Killer 杀死。经验教训是:小内存机器必须限制 JVM、精简 MySQL 配置并配置 swap,长期方案是迁移数据库或升级机器。

输入QQ号自动获取昵称

实现了在博客评论和回复框输入QQ号后自动获取昵称、头像并填充的功能。采用 uapis.cn 提供的 QQ 信息接口,使用正则校验和 jQuery AJAX 异步请求,失焦时触发。经过多接口对比后选定该稳定接口,并在友情链接/留言板和文章详情页完成集成。实现了前端格式验证、错误日志、跨域支持,并提出缓存、加载提示、备用接口及后端代理等优化建议。该功能简化了评论流程,显著提升用户体验。

Math.abs()竟然返回了负数?

Math.abs() 在普通数值上返回非负,但对 int 最小值 Integer.MIN_VALUE 会返回自身负数。原因是 int 采用补码表示,-Integer.MIN_VALUE 超出范围导致溢出,结果仍为 ‑2³¹。JDK 源码注释已说明这是规范行为。使用时应先判断该极值或转为 long、BigInteger,或使用 Math.addExact、Math.multiplyExact 等安全方法,并在单元测试中覆盖边界值。理解整数溢出是防止此类陷阱的关键。

从A标签跳转后JS失效?我踩过的坑和填坑方法

在博客列表页通过普通 `<a>` 跳转到文章详情时,页面加载正常但灯箱、复制按钮等 JS 功能失效,刷新或直接访问 URL 则一切正常。原因是浏览器在普通跳转时可能复用旧的 JS 环境或缓存页面,导致新页面的脚本未完整重新执行。临时解决办法是给链接加 `target="_self"`,强制完整加载;更根本的做法是改进 JS 初始化时机:在 `DOMContentLoaded`、`load`、`pageshow` 等事件中检查关键元素是否已出现,必要时使用 `setTimeout` 或 `Promise` 等方式等待后再调用 `initLightbox、initCopyButton` 等函数;文中还提供了基于 `PageManager` 的完整初始化管理器,能够在页面恢复、前进/后退等场景下安全重置并逐个等待所需元素。经验教训包括:不要盲目信任 `DOMContentLoaded`,要防御性地检查 DOM,了解浏览器缓存机制,并可考虑使用 `MutationObserver` 监听 DOM 变化。

深入解析CompletableFuture的设计哲学与实践

本文系统阐述了 Java 8 中 CompletableFuture 的设计哲学与实现细节。首先说明它受函数式编程和 Promise 思想驱动,提供链式、流式 API(thenApply、thenCompose 等)以实现回调与组合。随后解析内部状态机(INCOMPLETE、NORMAL、EXCEPTIONAL)和基于 Treiber 栈的依赖管理,揭示完成、异常传播的核心实现。接着通过电商订单处理案例演示并行检查、价格计算、库存扣减等业务的完整异步流水线,涵盖 thenCombine、allOf、异常处理、超时控制等实用技巧。最后列举条件执行、重试、超时降级等高级模式,展示 CompletableFuture 在高性能、可维护异步服务中的广泛应用。

Java7/8 中的 HashMap 和 ConcurrentHashMap 源码解析

文章系统地解析了 Java7/8 中 HashMap 与 ConcurrentHashMap 的实现细节。HashMap 采用数组+单向链表结构,容量始终为 2ⁿ,使用 loadFactor 与 threshold 控制扩容;put 时先计算 hash、定位桶、遍历链表去重,必要时双倍扩容并重新分配节点;get 通过相同的 hash 与 index 直接查找链表。ConcurrentHashMap 在此基础上引入 Segment(分段锁)实现并发,默认 16 段,每段内部类似 HashMap 并保持线程安全,初始化时将整体容量划分给各段,put 通过高位 hash 确定段并在对应 Segment 加锁后操作。全文重点说明了数组初始化、索引计算、节点插入、扩容机制以及并发控制的实现原理。