[{"data":1,"prerenderedAt":623},["ShallowReactive",2],{"java:database\u002F":3,"java-wiki-navigation":91},{"id":4,"title":5,"body":6,"commentId":77,"description":78,"difficulty":79,"draft":80,"extension":81,"meta":82,"navigation":83,"order":84,"path":85,"section":86,"seo":87,"stem":88,"updated":89,"__hash__":90},"java\u002Fjava\u002Fdatabase.md","数据库与缓存知识地图",{"type":7,"value":8,"toc":69},"minimark",[9,13,17,21,43,46,63,66],[10,11,12],"h2",{"id":12},"数据库知识的核心问题",[14,15,16],"p",{},"后端开发关注的不只是 SQL 能否执行，还要理解数据如何被定位、并发修改如何协调、失败后如何恢复，以及缓存加入后怎样维持可接受的一致性。",[10,18,20],{"id":19},"mysql","MySQL",[22,23,24,28,31,34,37,40],"ul",{},[25,26,27],"li",{},"B+Tree 与索引组织",[25,29,30],{},"联合索引和最左匹配",[25,32,33],{},"执行计划",[25,35,36],{},"MVCC 与 Read View",[25,38,39],{},"行锁、间隙锁和死锁",[25,41,42],{},"redo log、undo log 与 binlog",[10,44,45],{"id":45},"缓存",[22,47,48,51,54,57,60],{},[25,49,50],{},"Cache Aside",[25,52,53],{},"缓存穿透、击穿和雪崩",[25,55,56],{},"热点 Key",[25,58,59],{},"数据更新与失效",[25,61,62],{},"最终一致性",[10,64,65],{"id":65},"排查顺序",[14,67,68],{},"面对慢查询，先确认实际执行 SQL 和参数，再看执行计划、扫描行数、锁等待和数据分布。不要只根据 SQL 外观判断是否使用索引。",{"title":70,"searchDepth":71,"depth":71,"links":72},"",2,[73,74,75,76],{"id":12,"depth":71,"text":12},{"id":19,"depth":71,"text":20},{"id":45,"depth":71,"text":45},{"id":65,"depth":71,"text":65},"wiki:java:database","围绕索引、事务、锁、缓存与数据一致性，建立后端开发需要的数据库认知。","intermediate",false,"md",{},true,5,"\u002Fjava\u002Fdatabase","数据库",{"title":5,"description":78},"java\u002Fdatabase","2026-07-10","3gza7dGQZPwMSHFISiZ7Jy-iB_2rQD2ozomZ8OuiyHw",[92,182,294,401,498,547],{"id":93,"title":94,"body":95,"commentId":172,"description":173,"difficulty":174,"draft":80,"extension":81,"meta":175,"navigation":83,"order":176,"path":177,"section":178,"seo":179,"stem":180,"updated":89,"__hash__":181},"java\u002Fjava\u002Ffundamentals.md","Java 基础知识地图",{"type":7,"value":96,"toc":166},[97,100,103,106,131,134,137,140],[10,98,99],{"id":99},"这一部分解决什么问题",[14,101,102],{},"Java 基础不是 API 的罗列，而是理解类型、对象和运行时行为之间的关系。后续的并发、JVM 和框架知识都建立在这些概念之上。",[10,104,105],{"id":105},"知识路线",[107,108,109,112,119,122,125,128],"ol",{},[25,110,111],{},"基本类型、包装类型与自动装箱",[25,113,114,118],{},[115,116,117],"code",{},"String","、不可变对象与对象比较",[25,120,121],{},"集合框架与常见数据结构",[25,123,124],{},"泛型、类型擦除与边界",[25,126,127],{},"反射、注解与动态代理",[25,129,130],{},"异常体系和资源管理",[10,132,133],{"id":133},"推荐学习方式",[14,135,136],{},"先用一句话回答“它是什么”，再通过小段代码验证边界，最后把它放回 JVM 和框架运行机制中理解。知识库会逐步把每个主题拆成独立条目。",[10,138,139],{"id":139},"面试时容易出现的问题",[22,141,142,149,160,163],{},[25,143,144,145,148],{},"只背诵 ",[115,146,147],{},"HashMap"," 的结论，不理解哈希冲突和扩容成本。",[25,150,151,152,155,156,159],{},"把 ",[115,153,154],{},"=="," 和 ",[115,157,158],{},"equals"," 简化成“地址比较”和“内容比较”。",[25,161,162],{},"知道泛型语法，但无法解释类型擦除带来的限制。",[25,164,165],{},"会使用反射，却不了解它为什么被 Spring 等框架广泛使用。",{"title":70,"searchDepth":71,"depth":71,"links":167},[168,169,170,171],{"id":99,"depth":71,"text":99},{"id":105,"depth":71,"text":105},{"id":133,"depth":71,"text":133},{"id":139,"depth":71,"text":139},"wiki:java:fundamentals","Java 类型系统、集合、泛型、反射、异常与常用语言机制的学习入口。","basic",{},1,"\u002Fjava\u002Ffundamentals","Java 基础",{"title":94,"description":173},"java\u002Ffundamentals","TZ18cq4bXSr9iscSOTSlgfMfbmTp2H5kOdVxAbnY_2s",{"id":183,"title":184,"body":185,"commentId":286,"description":287,"difficulty":79,"draft":80,"extension":81,"meta":288,"navigation":83,"order":71,"path":289,"section":290,"seo":291,"stem":292,"updated":89,"__hash__":293},"java\u002Fjava\u002Fjvm.md","JVM 知识地图",{"type":7,"value":186,"toc":275},[187,191,194,196,200,214,217,231,234,248,251,265,268],[10,188,190],{"id":189},"为什么要理解-jvm","为什么要理解 JVM",[14,192,193],{},"JVM 把 Java 源代码和具体硬件隔开，但生产问题最终仍会落到内存、线程、字节码和操作系统资源上。理解 JVM 的目标不是记参数，而是能解释和诊断程序行为。",[10,195,105],{"id":105},[197,198,199],"h3",{"id":199},"类加载",[22,201,202,205,208,211],{},[25,203,204],{},"加载、验证、准备、解析和初始化",[25,206,207],{},"双亲委派模型",[25,209,210],{},"类加载器隔离",[25,212,213],{},"静态字段和初始化顺序",[197,215,216],{"id":216},"运行时数据区",[22,218,219,222,225,228],{},[25,220,221],{},"堆与对象分配",[25,223,224],{},"虚拟机栈与栈帧",[25,226,227],{},"方法区与元空间",[25,229,230],{},"直接内存",[197,232,233],{"id":233},"垃圾回收",[22,235,236,239,242,245],{},[25,237,238],{},"可达性分析",[25,240,241],{},"分代收集",[25,243,244],{},"CMS、G1 与现代收集器",[25,246,247],{},"停顿时间、吞吐量和内存占用之间的权衡",[197,249,250],{"id":250},"性能排查",[22,252,253,256,259,262],{},[25,254,255],{},"GC 日志",[25,257,258],{},"线程快照",[25,260,261],{},"堆转储",[25,263,264],{},"CPU、内存和锁竞争定位",[10,266,267],{"id":267},"一句话原则",[14,269,270,271,274],{},"先确定现象属于 CPU、内存、线程还是外部依赖，再选择工具；不要看到 ",[115,272,273],{},"OutOfMemoryError"," 就先调整堆大小。",{"title":70,"searchDepth":71,"depth":71,"links":276},[277,278,285],{"id":189,"depth":71,"text":190},{"id":105,"depth":71,"text":105,"children":279},[280,282,283,284],{"id":199,"depth":281,"text":199},3,{"id":216,"depth":281,"text":216},{"id":233,"depth":281,"text":233},{"id":250,"depth":281,"text":250},{"id":267,"depth":71,"text":267},"wiki:java:jvm","从类加载、运行时内存到垃圾回收与性能排查，理解 Java 程序如何真正运行。",{},"\u002Fjava\u002Fjvm","JVM",{"title":184,"description":287},"java\u002Fjvm","ZPK0OT5czgBvYvU-AowqKfXfaGqS5bqnDP2N5bWKN5k",{"id":295,"title":296,"body":297,"commentId":393,"description":394,"difficulty":79,"draft":80,"extension":81,"meta":395,"navigation":83,"order":281,"path":396,"section":397,"seo":398,"stem":399,"updated":89,"__hash__":400},"java\u002Fjava\u002Fconcurrency.md","Java 并发知识地图",{"type":7,"value":298,"toc":384},[299,302,305,312,315,325,328,331,333,367,370],[10,300,301],{"id":301},"并发问题的三个核心维度",[197,303,304],{"id":304},"可见性",[14,306,307,308,311],{},"一个线程修改的数据，何时能够被另一个线程观察到。",[115,309,310],{},"volatile","、锁和线程启动\u002F终止规则都与 happens-before 有关。",[197,313,314],{"id":314},"原子性",[14,316,317,318,321,322,324],{},"一个操作能否被其他线程观察到中间状态。",[115,319,320],{},"count++"," 即使使用 ",[115,323,310],{}," 也不是原子操作。",[197,326,327],{"id":327},"有序性",[14,329,330],{},"编译器和处理器可以在不改变单线程结果的前提下重排序。并发程序必须通过同步规则建立必要顺序。",[10,332,105],{"id":105},[107,334,335,338,343,349,352,355,358,364],{},[25,336,337],{},"Java 内存模型与 happens-before",[25,339,340,342],{},[115,341,310],{}," 与内存屏障",[25,344,345,348],{},[115,346,347],{},"synchronized"," 与对象监视器",[25,350,351],{},"CAS、原子类和 ABA 问题",[25,353,354],{},"AQS、锁和同步器",[25,356,357],{},"线程池与任务调度",[25,359,360,363],{},[115,361,362],{},"CompletableFuture"," 与异步编排",[25,365,366],{},"并发容器",[10,368,369],{"id":369},"生产实践原则",[22,371,372,375,378,381],{},[25,373,374],{},"尽量减少共享可变状态。",[25,376,377],{},"明确线程池的职责、队列容量和拒绝策略。",[25,379,380],{},"不要把耗时不可控的任务提交到公共线程池。",[25,382,383],{},"监控活跃线程数、队列长度、拒绝次数和任务耗时。",{"title":70,"searchDepth":71,"depth":71,"links":385},[386,391,392],{"id":301,"depth":71,"text":301,"children":387},[388,389,390],{"id":304,"depth":281,"text":304},{"id":314,"depth":281,"text":314},{"id":327,"depth":281,"text":327},{"id":105,"depth":71,"text":105},{"id":369,"depth":71,"text":369},"wiki:java:concurrency","理解可见性、原子性、有序性，以及 Java 并发工具如何建立在这些规则之上。",{},"\u002Fjava\u002Fconcurrency","并发编程",{"title":296,"description":394},"java\u002Fconcurrency","EkMZP12_4LdF-05WBbKP344weaqz3uif-3l5nazF3xk",{"id":402,"title":403,"body":404,"commentId":489,"description":490,"difficulty":79,"draft":80,"extension":81,"meta":491,"navigation":83,"order":492,"path":493,"section":494,"seo":495,"stem":496,"updated":89,"__hash__":497},"java\u002Fjava\u002Fspring.md","Spring 知识地图",{"type":7,"value":405,"toc":482},[406,410,413,417,434,438,452,455,472,475],[10,407,409],{"id":408},"理解-spring-的主线","理解 Spring 的主线",[14,411,412],{},"Spring 的核心不是注解数量，而是容器如何创建对象、建立依赖，并在合适的扩展点改变对象行为。",[10,414,416],{"id":415},"ioc-容器","IOC 容器",[22,418,419,422,425,428,431],{},[25,420,421],{},"BeanDefinition 的来源",[25,423,424],{},"Bean 创建生命周期",[25,426,427],{},"依赖注入",[25,429,430],{},"BeanPostProcessor",[25,432,433],{},"循环依赖",[10,435,437],{"id":436},"aop","AOP",[22,439,440,443,446,449],{},[25,441,442],{},"JDK 动态代理和 CGLIB",[25,444,445],{},"切点与通知",[25,447,448],{},"代理对象调用边界",[25,450,451],{},"自调用为什么可能导致切面失效",[10,453,454],{"id":454},"事务",[22,456,457,460,463,466,469],{},[25,458,459],{},"事务管理器",[25,461,462],{},"传播行为",[25,464,465],{},"隔离级别",[25,467,468],{},"回滚规则",[25,470,471],{},"声明式事务失效场景",[10,473,474],{"id":474},"学习建议",[14,476,477,478,481],{},"选择一条最短链路，从 ",[115,479,480],{},"ApplicationContext"," 启动到一个带事务的 Service 被调用，跟踪其中的对象创建、代理生成和拦截过程。这样比孤立背诵源码类名更有效。",{"title":70,"searchDepth":71,"depth":71,"links":483},[484,485,486,487,488],{"id":408,"depth":71,"text":409},{"id":415,"depth":71,"text":416},{"id":436,"depth":71,"text":437},{"id":454,"depth":71,"text":454},{"id":474,"depth":71,"text":474},"wiki:java:spring","从 IOC、AOP 和事务出发，理解 Spring 如何组织和增强应用程序。",{},4,"\u002Fjava\u002Fspring","Spring",{"title":403,"description":490},"java\u002Fspring","jZmHr0WwrtcGUGlcEdj8z-shlR3YZc-UdEZSfPZYgNE",{"id":4,"title":5,"body":499,"commentId":77,"description":78,"difficulty":79,"draft":80,"extension":81,"meta":545,"navigation":83,"order":84,"path":85,"section":86,"seo":546,"stem":88,"updated":89,"__hash__":90},{"type":7,"value":500,"toc":539},[501,503,505,507,521,523,535,537],[10,502,12],{"id":12},[14,504,16],{},[10,506,20],{"id":19},[22,508,509,511,513,515,517,519],{},[25,510,27],{},[25,512,30],{},[25,514,33],{},[25,516,36],{},[25,518,39],{},[25,520,42],{},[10,522,45],{"id":45},[22,524,525,527,529,531,533],{},[25,526,50],{},[25,528,53],{},[25,530,56],{},[25,532,59],{},[25,534,62],{},[10,536,65],{"id":65},[14,538,68],{},{"title":70,"searchDepth":71,"depth":71,"links":540},[541,542,543,544],{"id":12,"depth":71,"text":12},{"id":19,"depth":71,"text":20},{"id":45,"depth":71,"text":45},{"id":65,"depth":71,"text":65},{},{"title":5,"description":78},{"id":548,"title":549,"body":550,"commentId":614,"description":615,"difficulty":174,"draft":80,"extension":81,"meta":616,"navigation":83,"order":617,"path":618,"section":619,"seo":620,"stem":621,"updated":89,"__hash__":622},"java\u002Fjava\u002Finterview.md","Java 面试专题使用说明",{"type":7,"value":551,"toc":609},[552,555,558,561,594,597,606],[10,553,554],{"id":554},"这里不会做什么",[14,556,557],{},"不会把数百道问题堆在一个页面，也不会只给出适合背诵但无法解释的标准答案。",[10,559,560],{"id":560},"每个问题的组织方式",[107,562,563,570,576,582,588],{},[25,564,565,569],{},[566,567,568],"strong",{},"一句话回答","：先准确回答问题。",[25,571,572,575],{},[566,573,574],{},"核心原理","：说明这个结论为什么成立。",[25,577,578,581],{},[566,579,580],{},"代码验证","：使用尽可能小的例子验证边界。",[25,583,584,587],{},[566,585,586],{},"常见误区","：指出容易混淆的地方。",[25,589,590,593],{},[566,591,592],{},"继续追问","：把当前问题连接到更深层知识。",[10,595,596],{"id":596},"示例追问链",[598,599,604],"pre",{"className":600,"code":602,"language":603,"meta":70},[601],"language-text","HashMap 为什么线程不安全？\n  → put 操作包含哪些步骤？\n  → 扩容时发生什么？\n  → ConcurrentHashMap 如何降低竞争？\n  → JDK 不同版本的实现有什么变化？\n","text",[115,605,602],{"__ignoreMap":70},[14,607,608],{},"面试题的价值不是预测题目，而是帮助自己检查知识之间是否已经形成连接。",{"title":70,"searchDepth":71,"depth":71,"links":610},[611,612,613],{"id":554,"depth":71,"text":554},{"id":560,"depth":71,"text":560},{"id":596,"depth":71,"text":596},"wiki:java:interview","用简明回答、原理解释、代码验证和追问路径组织 Java 面试知识。",{},6,"\u002Fjava\u002Finterview","面试专题",{"title":549,"description":615},"java\u002Finterview","AWxAYmdi1IahbXu7QwVZPfsiCXbVU4YTMMoshQkzEl8",1783807996387]