Java 平台历代特性
Created|Updated|Java
|Word Count:16|Reading Time:1mins|Post Views:
Java 9 模块化,JDK 只依赖于 PATH 不依赖于 CLASSPATH。
Author: magicliang
Link: https://magicliang.github.io/2020/03/01/Java-%E5%B9%B3%E5%8F%B0%E5%8E%86%E4%BB%A3%E7%89%B9%E6%80%A7/
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles

2026-01-19
线程安全与锁优化
版本说明:本文主要基于 JDK 6 ~ JDK 14 的 HotSpot 虚拟机实现。需要注意的是,从 JDK 15 开始,偏向锁已被默认关闭并标记为废弃(JEP 374)。如果你使用的是 JDK 15+,文中关于偏向锁的内容仅作为历史参考。 线程安全 什么是线程安全 “当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。” 相对的线程安全,可以分成五个等级。但在深入讨论线程安全的分类之前,我们需要先理解 Java 内存模型——它是理解线程安全问题的理论基础。 Java 内存模型基础 Java 内存模型(Java Memory Model,JMM)是 Java 语言规范的一部分,定义了多线程程序中共享变量的访问规则。理解 JMM 是理解线程安全问题的基础。 为什么需要内存模型? 现代计算机系统中,CPU 与主内存之间存在巨大的速度差异。为了弥补这一差距,硬件层面引入了多级缓存(L1、L2、L3 Cache)。这带来了一个问...
2022-02-11
技术拾遗
Java Java 8 Lambda Java 8 Lambdas - A Peek Under the Hood What does $$ in javac generated name mean? lambda 表达式并不总是持有外部 enclosing object 的引用,如果它不访问任何外部变量,即不持有这样的引用。只要设计一个对比实验,就会发现引用过外部变量的lambda实例才会产生一个 arg 的隐式参数引用。而内部类内部总是含有一个this$0。 lambda表达式是词法作用域的-意思是不产生新的作用域,不产生任何shadowing问题。它可以无缝访问外部作用域的东西,就好像从一个 if block 里访问一个方法里的其他变量一样。但,同样地,不能声明新变量。

2020-03-29
Java 注解和配置
Java 的原生注解 meta annotation @Inherited @Inherited 是一个元注解(annotations applied to other annotations 注解其他注解的注解),也是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。 **@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。**其查找过程是:反射 API 会在查找 @Inherited 标注的注解的时候,自底向上往继承树上方查找。 12345678910111213141516171819202122@Inherited@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface MyAnnotation { String value() default "Default Value";}@MyA...
2026-05-21
写一个 lambda 规约器
上一篇文章把 lambda 演算拆成三种表达式:变量、函数、调用。示例只做了最小的一步替换,用来说明函数应用可以变成表达式重写。 本文把这件事补成一个规约器:给定一个 lambda 表达式,持续执行 beta 规约,打印每一步轨迹,并处理替换过程中最容易出错的变量捕获问题。这个规约器仍然很小,但已经具备解释器和 AST 重写器的基本骨架。 规约器要解决什么 lambda 演算的核心计算规则是 beta 规约: 12(x -> body) argument -> body 中的自由 x 替换成 argument 例如: 12(x -> x) a -> a 更复杂一点的例子: 123(((x -> (y -> x)) a) b) -> ((y -> a) b) -> a 规约器需要完成三件事: 职责 作用 找到可规约位置 判断哪一个调用先执行 做安全替换 只替换自由变量,避免误改绑定变量 重复执行 直到表达式无法继续变化 这和解释器很接近。区别在于解释器通常维护环境和值,lambda 规约器直...

2026-09-07
从零构建现代搜索引擎(14):搜索 API 与第一个网页界面
前面十三篇实现了一个完整的搜索引擎内核:倒排索引、BM25 评分、段文件、崩溃恢复、摘要和高亮。但它只能通过 Java main 方法调用——没有 API,没有界面,用户没法用。 本篇把搜索引擎包装成一个 HTTP 服务,加一个最简单的网页界面,让用户在浏览器中输入查询、看到结果、翻页。同时处理搜索服务必须面对的工程问题:参数校验、超时、错误反馈。 HTTP 搜索端点 JDK 内置 HTTP Server Java 25 自带 com.sun.net.httpserver.HttpServer,不需要引入 Spring Boot 或其他框架。教学场景下它足够: 12345HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);server.createContext("/api/search", this::handleSearch);server.createContext("/", this::handleStatic);server.setExecu...

2026-09-06
从零构建现代搜索引擎(06):中文、英文和代码怎样变成词项
前五篇完成了文档的采集、导入和评测基线。文档以纯文本的形式进入系统,但搜索是以词为单位进行的——查询 “Java 内存模型” 需要把这五个字拆成能和索引匹配的词项。英文有空格做天然分隔,中文没有;版本号 3.14.1 不应该在小数点处断开;NullPointerException 既需要保留完整形式也需要拆成子词。 本篇设计一个分析器(Analyzer),将原始文本转换为可索引的词项流,记录每个词项的位置和偏移量。 分析器的三阶段模型 文本分析拆成三步: 1原始文本 → Tokenizer → Token Filter → 词项流(Term Stream) Tokenizer 把连续文本切成一个个 token。Token Filter 对 token 做后处理:小写化、停用词移除、同义词展开。每个 token 携带四项信息: 123456public record Token( String term, // 词项文本 int position, // 在词项流中的序号(0-based) int startOffset, // 在原始...
Announcement
人生只是,守株待兔
