<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>JDK 24 on miti99</title><link>https://miti99.com/tags/jdk-24/</link><description>Recent content in JDK 24 on miti99</description><generator>Hugo -- gohugo.io</generator><language>vi</language><lastBuildDate>Mon, 28 Sep 2026 09:25:57 +0700</lastBuildDate><atom:link href="https://miti99.com/tags/jdk-24/index.xml" rel="self" type="application/rss+xml"/><item><title>Newsletter #28</title><link>https://miti99.com/post/2025/05/15/</link><pubDate>Thu, 15 May 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/05/15/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #28.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="how-airbnb-measures-listing-lifetime-value"&gt;&lt;a class="link" href="https://medium.com/airbnb-engineering/how-airbnb-measures-listing-lifetime-value-a603bf05142c" target="_blank" rel="noopener"
&gt;How Airbnb Measures Listing Lifetime Value&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Nhóm Khoa học dữ liệu của Airbnb giới thiệu khung đo lường giá trị vòng đời của một chỗ ở (Listing Lifetime Value - LTV) trên một nền tảng hai phía, nơi có nhiều người bán và nhiều người mua cùng lúc. Khung này gồm ba đại lượng. LTV cơ sở là tổng số lượt đặt phòng mà một chỗ ở dự kiến nhận được trong 365 ngày tới, được ước lượng bằng học máy từ các đặc trưng như lịch trống, giá, vị trí, thâm niên của chủ nhà, rồi quy về hiện giá. LTV gia tăng lấy LTV cơ sở trừ đi phần &amp;ldquo;ăn thịt&amp;rdquo; từ chỗ ở khác, tức những lượt đặt vẫn xảy ra kể cả khi chỗ ở đó không tồn tại. Cuối cùng, LTV gia tăng nhờ tiếp thị đo phần giá trị mà các chiến dịch nội bộ thực sự tạo thêm.&lt;/p&gt;
&lt;p&gt;Có ba thách thức khi triển khai. Thứ nhất, nhãn huấn luyện chỉ có sau 365 ngày nên mô hình dễ sai lệch khi thị trường biến động như thời COVID-19; nhóm đã rút ngắn cửa sổ huấn luyện, bổ sung dữ liệu địa lý chi tiết và chuyển sang LightGBM. Thứ hai, không bao giờ quan sát được &amp;ldquo;sự thật&amp;rdquo; về tính gia tăng, nên họ ước lượng một hàm sản xuất mô tả cách tổng cung và tổng cầu của từng phân khúc tạo ra lượt đặt: phân khúc cầu cao, cung thấp thì một chỗ ở mới mang lại nhiều giá trị gia tăng hơn. Thứ ba, để xử lý bất định, dự đoán được điều chỉnh hằng ngày dựa trên số lượt đặt đã thực nhận.&lt;/p&gt;
&lt;h2 id="six-jdk-24-features-you-should-know-about"&gt;&lt;a class="link" href="https://foojay.io/today/six-jdk-24-features-you-should-know-about/" target="_blank" rel="noopener"
&gt;Six JDK 24 Features You Should Know About&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Simon Ritter (Azul) điểm qua sáu tính năng đáng chú ý nhất của JDK 24, phiên bản phát hành ngày 18/3/2025 với 24 JEP, nhiều nhất kể từ khi Java chuyển sang lịch phát hành sáu tháng một lần. JEP 483 thuộc Project Leyden cho phép các lớp của ứng dụng ở sẵn trạng thái đã nạp và liên kết ngay khi JVM khởi động, dựa trên nền tảng Application Class Data Sharing, nhờ đó giảm thời gian khởi động. JEP 485 (Stream Gatherers) bổ sung giao diện Gatherer để lập trình viên tự định nghĩa thao tác trung gian cho Stream, tương tự cách Collector phục vụ thao tác kết thúc. JEP 491 gỡ bỏ một hạn chế lớn của virtual thread: trước đây khi bị chặn bên trong khối synchronized, virtual thread vẫn &amp;ldquo;ghim&amp;rdquo; luồng nền vì monitor gắn với luồng nền; nay monitor được gắn với chính virtual thread.&lt;/p&gt;
&lt;p&gt;Ba JEP còn lại mang tính dọn dẹp. JEP 486 vô hiệu hóa vĩnh viễn Security Manager, vốn đã bị đánh dấu lỗi thời từ JDK 17 và hầu như không còn được dùng để bảo vệ mã phía máy chủ; ứng dụng nào còn phụ thuộc vào nó có thể phải thay đổi kiến trúc khi nâng cấp. JEP 498 khiến JVM phát cảnh báo ở lần đầu gọi các phương thức truy cập bộ nhớ trong sun.misc.Unsafe, khuyến khích chuyển sang VarHandle và Foreign Function &amp;amp; Memory API. JEP 501 đánh dấu cổng x86 32-bit (chỉ còn trên Linux, bản Windows đã bị gỡ ở JDK 21) để loại bỏ trong tương lai. Đây là bản tóm tắt gọn giúp bạn chuẩn bị trước khi lên JDK 25, phiên bản hỗ trợ dài hạn tiếp theo.&lt;/p&gt;
&lt;h2 id="javaone-2025-function-and-memory-access-in-pure-java"&gt;&lt;a class="link" href="https://www.infoq.com/news/2025/04/foreign-function-minborg/" target="_blank" rel="noopener"
&gt;JavaOne 2025: Function and Memory Access in Pure Java&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết trên InfoQ tường thuật phần trình bày của Per-Åke Minborg (Oracle) tại JavaOne 2025 về Foreign Function &amp;amp; Memory API (FFM, JEP 454), được chính thức đưa vào JDK 22 trong khuôn khổ Project Panama nhằm thay thế JNI. Theo Minborg, JNI buộc lập trình viên kết hợp Java và C một cách mong manh, tốn kém khi bảo trì và triển khai, truyền dữ liệu cồng kềnh, chỉ hỗ trợ kiểu nguyên thủy và đối tượng Java, không giải phóng bộ nhớ một cách chủ động và chỉ định địa chỉ được khoảng 2 GB. Các thư viện như JNA, JNR hay JavaCPP từng thử khắc phục nhưng không được đón nhận rộng rãi.&lt;/p&gt;
&lt;p&gt;Ở phần bộ nhớ, &lt;code&gt;MemorySegment&lt;/code&gt; đại diện cho một vùng nhớ liên tục với địa chỉ 64-bit, được bảo vệ khỏi truy cập ngoài giới hạn, truy cập sau khi giải phóng và truy cập từ luồng không được phép. Vòng đời vùng nhớ do &lt;code&gt;Arena&lt;/code&gt; quản lý với bốn loại Global, Auto, Confined và Shared. &lt;code&gt;ValueLayout&lt;/code&gt; và &lt;code&gt;MemoryLayout&lt;/code&gt; mô tả dữ liệu theo cấu trúc để lấy ra &lt;code&gt;VarHandle&lt;/code&gt; thay vì tự tính độ lệch bằng tay, và khai báo các &lt;code&gt;VarHandle&lt;/code&gt; là &lt;code&gt;final&lt;/code&gt; rất quan trọng để đạt hiệu năng tốt nhất. Ở phần hàm, công cụ &lt;code&gt;jextract&lt;/code&gt; tự sinh liên kết Java từ tệp header của thư viện native, chẳng hạn gọi thẳng hàm &lt;code&gt;qsort&lt;/code&gt; của C từ Java. Tóm lại, FFM mang đến cách truy cập bộ nhớ native an toàn, hiệu quả và gọi hàm native bằng mã Java thuần, không phải viết và duy trì mã C.&lt;/p&gt;
&lt;h2 id="ultimate-guide-to-project-reactor-thread-locals-and-context-propagation"&gt;&lt;a class="link" href="https://4comprehension.com/ultimate-guide-to-project-reactor-thread-locals-and-context-propagation/" target="_blank" rel="noopener"
&gt;Ultimate Guide to Project Reactor, Thread-Locals and Context Propagation&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Grzegorz Piwowarek giải thích vì sao việc truyền ngữ cảnh (context propagation) luôn là chủ đề khó trong Project Reactor. &lt;code&gt;ThreadLocal&amp;lt;X&amp;gt;&lt;/code&gt; về bản chất giống &lt;code&gt;Map&amp;lt;Thread, X&amp;gt;&lt;/code&gt;, trong khi một chuỗi phản ứng có thể nhảy sang luồng khác qua các toán tử như &lt;code&gt;publishOn()&lt;/code&gt;, khiến giá trị ThreadLocal biến mất giữa chừng. Giải pháp cơ bản là Context của Reactor: ghi giá trị bằng &lt;code&gt;contextWrite()&lt;/code&gt; và đọc lại bằng cách đổi &lt;code&gt;map()&lt;/code&gt; thành &lt;code&gt;flatMap()&lt;/code&gt; kết hợp &lt;code&gt;Mono.deferContextual()&lt;/code&gt;. Tác giả cũng lưu ý rằng nếu có thể lấy giá trị trước khi vào chuỗi phản ứng thì cứ dùng biến thông thường cho đơn giản.&lt;/p&gt;
&lt;p&gt;Phần khó hơn là tích hợp với các công cụ dựa vào ThreadLocal như ghi nhật ký bằng MDC: phải khôi phục giá trị vào MDC trước mỗi lambda, và mẫu execute-around giúp gói phần lặp lại vào một phương thức tiện ích &lt;code&gt;withMDC&lt;/code&gt;. Với &lt;code&gt;doOnNext()&lt;/code&gt; vốn không truy cập được Context, có thể dùng &lt;code&gt;doOnEach()&lt;/code&gt;, kiểm tra tín hiệu &lt;code&gt;onNext&lt;/code&gt; rồi lấy ngữ cảnh từ đối tượng &lt;code&gt;Signal&lt;/code&gt;. Cuối cùng là truyền ngữ cảnh tự động: thêm thư viện &lt;code&gt;io.micrometer:context-propagation&lt;/code&gt;, gọi &lt;code&gt;Hooks.enableAutomaticContextPropagation()&lt;/code&gt; và đăng ký một &lt;code&gt;ThreadLocalAccessor&lt;/code&gt;, Reactor sẽ tự khôi phục giá trị ở mỗi bước. Cách này tiện lợi nhưng có thể tốn kém hơn cách thủ công, và vì đây là thiết lập toàn cục cho cả JVM nên nó ảnh hưởng tới mọi chuỗi Reactor trong tiến trình; hãy cân nhắc theo từng trường hợp cụ thể.&lt;/p&gt;
&lt;h2 id="jdk-24-g1parallelserial-gc-changes"&gt;&lt;a class="link" href="https://tschatzl.github.io/2025/04/01/jdk24-g1-serial-parallel-gc-changes.html" target="_blank" rel="noopener"
&gt;JDK 24 G1/Parallel/Serial GC Changes&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Thomas Schatzl (Oracle) tổng hợp thay đổi của các bộ thu gom rác dừng toàn bộ (stop-the-world) trong JDK 24. Với Parallel GC, một số thao tác đồng bộ không cần thiết trong vòng lặp di tản đã được loại bỏ (JDK-8269870); Serial GC tiếp tục được dọn dẹp và tái cấu trúc. Thay đổi đáng kể nhất nằm ở G1: để đạt mục tiêu thời gian tạm dừng, G1 dự đoán các chi phí như sao chép bộ nhớ hay cập nhật tham chiếu, nhưng giá trị khởi tạo được đo từ lâu trên một máy SPARC cũ nên rất bảo thủ, khiến G1 cần khoảng 30 lần thu gom mới thích nghi. Với JDK-8343189, giá trị đo thực tế đầu tiên ghi đè thẳng lên giá trị mặc định, giúp G1 thích nghi nhanh hơn nhiều, đổi lại có thể vượt mục tiêu tạm dừng ở vài lần đầu. Ngoài ra, G1 giờ quản lý remembered set của cả thế hệ trẻ như một đơn vị duy nhất (JDK-8336086), giảm trùng lặp và tiết kiệm bộ nhớ native.&lt;/p&gt;
&lt;p&gt;Tác giả cũng hé lộ lộ trình JDK 25: việc gộp remembered set cho các vùng thế hệ cũ (JDK-8343782) đã được tích hợp, còn rào chắn ghi (write barrier) của G1 được làm lại hoàn toàn, hứa hẹn tăng thông lượng tới 10%, tạm dừng ngắn hơn và sinh mã tốt hơn, đổi lại cần thêm một khối bộ nhớ tĩnh khoảng 0,2% kích thước heap. Ngoài ra còn có thảo luận về việc đưa Automatic Heap Sizing giống ZGC sang các bộ thu gom này với đóng góp từ Microsoft và Google, cũng như biến G1 thành bộ thu gom mặc định thực sự thay cho Serial GC ở môi trường ít tài nguyên.&lt;/p&gt;
&lt;h2 id="making-makefiles-for-fun-and-profit"&gt;&lt;a class="link" href="https://dev.to/aws/making-makefiles-for-fun-and-profit-kl6" target="_blank" rel="noopener"
&gt;Making Makefiles for fun and profit&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Darko Mesaroš (AWS) nhìn lại &lt;code&gt;make&lt;/code&gt;, công cụ tự động hóa xây dựng đã 48 tuổi do Stuart Feldman tạo ra để lập trình viên không còn quên biên dịch lại những tệp vừa sửa. So với một kịch bản &lt;code&gt;build.sh&lt;/code&gt; biên dịch lại mọi thứ, &lt;code&gt;make&lt;/code&gt; chỉ xây dựng lại phần đã thay đổi. Tác giả mổ xẻ một Makefile cho dự án C: các biến (make gọi là macro), đích &lt;code&gt;all&lt;/code&gt; chạy mặc định, quy tắc liên kết dùng các macro có sẵn &lt;code&gt;$@&lt;/code&gt; và &lt;code&gt;$^&lt;/code&gt;, quy tắc mẫu &lt;code&gt;%.o: %.c&lt;/code&gt; để biên dịch từng tệp, đích &lt;code&gt;clean&lt;/code&gt; để dọn dẹp, và &lt;code&gt;.PHONY&lt;/code&gt; để tránh xung đột khi thư mục có tệp trùng tên với đích.&lt;/p&gt;
&lt;p&gt;Phần sau cho thấy &lt;code&gt;make&lt;/code&gt; hữu ích vượt xa ngôn ngữ C: tự động hóa Terraform với việc nhận diện hệ điều hành và cảnh báo kỹ trước khi chạy &lt;code&gt;terraform destroy&lt;/code&gt;, dựng môi trường phát triển cục bộ bằng Docker với Postgres và Redis cho một dự án Rust, quản lý dự án AWS CDK viết bằng TypeScript và Rust với các lệnh cài đặt, xây dựng, triển khai từng phần hoặc toàn bộ và kiểm thử cục bộ cùng DynamoDB Local, cũng như triển khai trang web tĩnh lên S3 kèm AWS Amplify. Để vượt qua cú pháp khó đọc, tác giả dùng Amazon Q Developer CLI sinh Makefile tự động, kể cả việc truy vấn động mã ứng dụng Amplify. Bài viết là lời nhắc rằng công cụ cũ vẫn rất đáng dùng, nhất là khi có trợ lý AI giúp hạ thấp rào cản ban đầu.&lt;/p&gt;
&lt;h2 id="improving-pinterest-search-relevance-using-large-language-models"&gt;&lt;a class="link" href="https://medium.com/pinterest-engineering/improving-pinterest-search-relevance-using-large-language-models-4cd938d4e892" target="_blank" rel="noopener"
&gt;Improving Pinterest Search Relevance Using Large Language Models&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Nhóm kỹ sư Pinterest chia sẻ cách họ dùng mô hình ngôn ngữ lớn (LLM) để cải thiện độ liên quan của kết quả tìm kiếm, tức mức độ một Pin thực sự đáp ứng nhu cầu của truy vấn thay vì chỉ dựa vào lượt tương tác trong quá khứ. Mô hình &amp;ldquo;thầy&amp;rdquo; là một cross-encoder nhận truy vấn cùng văn bản mô tả Pin, được tinh chỉnh trên dữ liệu gán nhãn thủ công như một bài toán phân loại nhiều lớp. Văn bản của Pin được làm giàu từ nhiều nguồn: tiêu đề và mô tả, chú thích ảnh do mô hình BLIP sinh ra, các truy vấn có tương tác cao nhất, tên bảng mà người dùng lưu Pin vào và tiêu đề trang liên kết. Trong các thử nghiệm, Llama-3-8B (tinh chỉnh bằng qLoRA) vượt BERT đa ngôn ngữ 12,5% và mô hình cơ sở 19,7% về độ chính xác,.&lt;/p&gt;
&lt;p&gt;Vì LLM quá chậm và tốn kém để phục vụ trực tiếp, Pinterest dùng kỹ thuật chưng cất tri thức: mô hình thầy gán nhãn hằng ngày cho tập dữ liệu hàng tỷ dòng, rồi huấn luyện một mô hình &amp;ldquo;trò&amp;rdquo; gọn nhẹ dựa trên các embedding như SearchSAGE, PinSAGE, embedding hình ảnh cùng các đặc trưng khớp văn bản như BM25. Nhờ mô hình thầy đa ngôn ngữ, hệ thống khái quát tốt sang những ngôn ngữ và quốc gia không có dữ liệu gán nhãn. Thử nghiệm A/B cho thấy độ liên quan tăng 2,18% theo nDCG@20 và tỷ lệ hoàn thành tìm kiếm tăng hơn 1,5%. Hướng tiếp theo là phục vụ LLM trực tiếp, dùng mô hình thị giác – ngôn ngữ và học chủ động.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #20</title><link>https://miti99.com/post/2025/05/07/</link><pubDate>Wed, 07 May 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/05/07/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #20.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="performance-improvements-in-jdk-24"&gt;&lt;a class="link" href="https://inside.java/2025/03/19/performance-improvements-in-jdk24/" target="_blank" rel="noopener"
&gt;Performance Improvements in JDK 24&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết trên Inside.java tổng hợp những cải tiến hiệu năng đáng chú ý nhất của JDK 24 so với JDK 23, liệt kê theo từng mục trong hệ thống theo dõi lỗi của JDK. Ở nhóm thư viện lõi, các thao tác hàng loạt của Foreign Function &amp;amp; Memory API như &lt;code&gt;MemorySegment::fill&lt;/code&gt;, &lt;code&gt;copy&lt;/code&gt; và &lt;code&gt;mismatch&lt;/code&gt; giờ được xử lý bằng mã Java thuần khi vùng nhớ đủ nhỏ, tránh chi phí chuyển sang mã native qua Unsafe. Việc nối chuỗi chuyển sang dùng các lớp ẩn (hidden class) có thể lưu đệm và tái sử dụng thay vì dựng nhiều &lt;code&gt;MethodHandle&lt;/code&gt; trung gian; các thuật toán SHA3 nhanh hơn tới 27% nhờ giảm chuyển đổi giữa mảng byte và mảng long; còn quá trình chuyển sang ClassFile API được tối ưu để giảm ảnh hưởng tới thời gian khởi động.&lt;/p&gt;
&lt;p&gt;Ở tầng runtime, JEP 491 cho phép virtual thread bị chặn trong khối &lt;code&gt;synchronized&lt;/code&gt; nhả luồng mang (carrier thread) thay vì bị ghim cố định, giúp mã dùng &lt;code&gt;synchronized&lt;/code&gt; mở rộng tốt hơn. &lt;code&gt;String::indexOf&lt;/code&gt; nhanh hơn khoảng 1,3 lần trên nền tảng x64 hỗ trợ AVX2. JEP 483 (Ahead-of-Time Class Loading &amp;amp; Linking), sản phẩm đầu tiên của Project Leyden, dùng bộ nhớ đệm AOT để cải thiện thời gian khởi động khoảng 42% trong ví dụ của bài. JEP 450 thử nghiệm header đối tượng chỉ 8 byte, giúp giảm 10–20% bộ nhớ với các khối lượng công việc thông thường. Ngoài ra, nền tảng RISC-V cũng nhận thêm nhiều hàm intrinsic như CRC32, Adler32 cùng các tối ưu cho so sánh chuỗi và đảo byte.&lt;/p&gt;
&lt;h2 id="clean-your-memory-from-finalize-to-cleaner"&gt;&lt;a class="link" href="https://blog.frankel.ch/java-cleaner/" target="_blank" rel="noopener"
&gt;Clean your Memory: From Finalize to Cleaner&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Stefano Fago giải thích rằng bộ thu gom rác (GC) của Java chỉ quản lý bộ nhớ, không tự giải phóng các tài nguyên bên ngoài như socket hay file handle; nếu quản lý sai, ứng dụng có thể rò rỉ tài nguyên, chậm dần hoặc sập. Cách cũ là ghi đè &lt;code&gt;finalize()&lt;/code&gt;, nhưng phương thức này đã bị đánh dấu lỗi thời vì thời điểm chạy không đoán trước được, đối tượng phải qua thêm một chu kỳ GC mới được thu hồi, có thể gây rò rỉ nếu đối tượng vô tình bị giữ lại, và luồng Finalizer riêng dễ gây tranh chấp. Giải pháp thay thế là Cleaner API, có từ Java 9: bên dưới nó dùng &lt;code&gt;PhantomReference&lt;/code&gt; cùng một luồng daemon nền, nhưng che giấu sự phức tạp của các lớp Reference. Bạn đăng ký đối tượng kèm một hành động dọn dẹp, và khi đối tượng không còn truy cập được, hành động đó được đưa vào hàng đợi để chạy trên luồng nền.&lt;/p&gt;
&lt;p&gt;Cleaner có thể kết hợp với &lt;code&gt;AutoCloseable&lt;/code&gt;: phương thức &lt;code&gt;close()&lt;/code&gt; gọi &lt;code&gt;clean()&lt;/code&gt; để dọn dẹp ngay khi cần, còn Cleaner đóng vai trò lưới an toàn. Tuy vậy, tác giả nhấn mạnh chỉ nên dùng Cleaner khi không thể giải phóng tài nguyên bằng try-with-resources hoặc gọi &lt;code&gt;close()&lt;/code&gt; tường minh, vì cơ chế này dọn dẹp bất đồng bộ và tốn chi phí hơn do cần luồng nền. Khi viết hành động dọn dẹp, nên tránh lambda vì dễ vô tình giữ tham chiếu tới chính đối tượng cần dọn, khiến nó không bao giờ được thu hồi; hành động cũng cần ngắn gọn và không chặn, vì nhiều hành động có thể chạy đồng thời trên cùng một Cleaner.&lt;/p&gt;
&lt;h2 id="5-hidden-git-tips-for-java-developers"&gt;&lt;a class="link" href="https://www.azul.com/blog/5-hidden-git-tips-for-java-developers/" target="_blank" rel="noopener"
&gt;5 Hidden Git Tips for Java Developers&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Trên blog của Azul, Luqman Saeed giới thiệu năm tính năng ít được chú ý của Git, vượt ra ngoài bộ ba quen thuộc commit, push và pull, kèm ví dụ gắn với dự án Java. Đầu tiên là &lt;code&gt;git bisect&lt;/code&gt;: khi không rõ commit nào gây lỗi, bạn đánh dấu commit hiện tại là xấu (&lt;code&gt;git bisect bad&lt;/code&gt;) và một commit cũ còn chạy đúng là tốt (&lt;code&gt;git bisect good &amp;lt;commit-hash&amp;gt;&lt;/code&gt;), rồi Git tìm kiếm nhị phân bằng cách lần lượt checkout commit ở giữa để bạn kiểm thử cho đến khi tìm ra thủ phạm; kết thúc bằng &lt;code&gt;git bisect reset&lt;/code&gt;. Tiếp theo, &lt;code&gt;git blame &amp;lt;tên-tệp&amp;gt;&lt;/code&gt; cho biết ai sửa từng dòng lần cuối và vào lúc nào (thêm cờ &lt;code&gt;-L 50,60&lt;/code&gt; để chỉ xem một đoạn), giúp bạn hiểu bối cảnh trước khi gỡ lỗi hay tái cấu trúc. Khi phải chuyển việc giữa chừng, &lt;code&gt;git stash&lt;/code&gt; cất tạm các thay đổi chưa commit và &lt;code&gt;git stash pop&lt;/code&gt; lấy chúng lại; &lt;code&gt;git stash list&lt;/code&gt; cùng &lt;code&gt;git stash apply &amp;lt;stash-id&amp;gt;&lt;/code&gt; giúp quản lý nhiều lần cất.&lt;/p&gt;
&lt;p&gt;Với các tệp tạm do Maven hay Gradle sinh ra như &lt;code&gt;.class&lt;/code&gt; hoặc thư mục &lt;code&gt;target/&lt;/code&gt;, &lt;code&gt;git clean -n&lt;/code&gt; cho xem trước, &lt;code&gt;-f&lt;/code&gt; xóa tệp chưa theo dõi, &lt;code&gt;-fd&lt;/code&gt; xóa cả thư mục, còn &lt;code&gt;-x&lt;/code&gt; xóa luôn các tệp bị bỏ qua như &lt;code&gt;.idea/&lt;/code&gt;. Cuối cùng, git hooks là các script tự chạy trước hoặc sau những sự kiện như commit, push hay merge; chẳng hạn một hook &lt;code&gt;pre-commit&lt;/code&gt; đặt trong &lt;code&gt;.git/hooks&lt;/code&gt; có thể chạy &lt;code&gt;mvn test&lt;/code&gt; và hủy commit nếu kiểm thử thất bại. Mẹo bổ sung: &lt;code&gt;git checkout -&lt;/code&gt; đưa bạn về nhánh vừa làm việc trước đó mà không cần gõ lại tên nhánh, vừa tiết kiệm thời gian vừa tránh gõ sai.&lt;/p&gt;
&lt;h2 id="simplify-your-system-by-challenging-the-status-quo-and-learning-from-other-ecosystems"&gt;&lt;a class="link" href="https://www.infoq.com/podcasts/simplify-system-learning-ecosystems/" target="_blank" rel="noopener"
&gt;Simplify Your System by Challenging the Status-Quo and Learning from Other Ecosystems&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Trong podcast của InfoQ, Max Rydahl Andersen, Distinguished Engineer tại Red Hat và tác giả của JBang, kể rằng sau một năm tạm rời Java, khi quay lại ông nhận ra cộng đồng đã tích tụ quá nhiều độ phức tạp, giống như &amp;ldquo;một nghìn vết cắt giấy&amp;rdquo; (thousand paper cuts): mỗi tính năng nhỏ đều hữu ích nhưng cộng lại thành gánh nặng. Quarkus, dự án ông tham gia, đảo ngược cách làm truyền thống bằng cách dời phần lớn xử lý sang thời điểm build thay vì runtime, nhờ đó ứng dụng khởi động rất nhanh. Tốc độ này còn mở ra trải nghiệm phát triển tốt hơn: tải lại nóng (hot reload), kiểm thử liên tục, Dev Services tự dựng các dịch vụ như PostgreSQL hay Kafka, và giao diện chat để thử dịch vụ AI qua LangChain4J ngay trong Dev UI.&lt;/p&gt;
&lt;p&gt;Với JBang, ông lấy cảm hứng từ Python và Node.js để chạy Java chỉ từ một tệp duy nhất, thậm chí tự tải JDK nếu máy chưa cài; ông tuyên bố nếu tìm được môi trường phát triển nào dễ cài đặt hơn thì đó là lỗi của JBang. Max cũng cho rằng AI không thay thế được nền tảng kỹ thuật phần mềm và tư duy hệ thống, đồng thời cảnh báo AI sẽ giúp khai thác lỗ hổng (CVE) nhanh hơn, nên các hệ thống cũ cần được cập nhật thường xuyên hơn. Thông điệp chung của buổi trò chuyện: hãy thách thức hiện trạng và học hỏi từ các hệ sinh thái khác để giữ hệ thống đơn giản.&lt;/p&gt;
&lt;h2 id="about"&gt;&lt;a class="link" href="https://tryingthings.wordpress.com/2025/03/24/about-vibe-coding/" target="_blank" rel="noopener"
&gt;About &amp;ldquo;vibe coding&amp;rdquo;&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Sorin Costea viết ngắn gọn về trào lưu &amp;ldquo;vibe coding&amp;rdquo;, tức để AI viết mã nguồn thay cho lập trình viên. Sau khi đọc bài &amp;ldquo;Vibe coding vs Reality&amp;rdquo;, ông thấy không chỉ riêng ông hoài nghi, vì chính ông đã thử Cursor với một dự án Java Maven và công cụ này thậm chí không đổi tên nổi một lớp: lúc thì chỉ đổi tên lớp mà không đổi tên tệp, lúc được yêu cầu lại thì tạo ra một tệp rỗng mang tên mới, và chuyện đó lặp lại hai lần.&lt;/p&gt;
&lt;p&gt;Khi chia sẻ trên Hacker News, ông chỉ nhận được những phản hồi kiểu &amp;ldquo;haha Java&amp;rdquo;, khiến ông tự hỏi Cursor chỉ được huấn luyện cho các framework frontend thịnh hành hay những người ủng hộ nó không quan tâm đến ứng dụng thực tế. Kết quả là ông gỡ Cursor và càng hoài nghi các giải pháp AI &amp;ldquo;thần kỳ&amp;rdquo;, dù vẫn để ngỏ khả năng thay đổi: &amp;ldquo;Nhưng năm sau? Năm sau sẽ biết.&amp;rdquo;&lt;/p&gt;
&lt;h2 id="visual-focused-algorithms-cheat-sheet"&gt;&lt;a class="link" href="https://photonlines.substack.com/p/visual-focused-algorithms-cheat-sheet" target="_blank" rel="noopener"
&gt;Visual-Focused Algorithms Cheat Sheet&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Nick M tổng hợp một bảng tra cứu (cheat sheet) thiên về hình ảnh cho các thuật toán quan trọng được dùng trong thực tế, nối tiếp bảng tra cứu cấu trúc dữ liệu trước đó của ông; mỗi thuật toán được giải thích bằng ví dụ đời thường và hình minh họa. Phần sắp xếp đi từ Selection Sort và Insertion Sort, đơn giản nhưng có độ phức tạp O(n²), đến Heap Sort, Quick Sort và Merge Sort với O(n log n), rồi Tim Sort, thuật toán lai giữa Insertion Sort và Merge Sort được dùng trong Python và Java. Phần tìm kiếm gồm Binary Search với O(log n) cùng DFS và BFS để duyệt đồ thị theo chiều sâu và chiều rộng. Phần đồ thị trình bày Prim và Kruskal để tìm cây khung nhỏ nhất, Dijkstra và Bellman-Ford để tìm đường đi ngắn nhất (Bellman-Ford xử lý được cả trọng số âm), A* dùng hàm ước lượng (heuristic), cùng Union-Find và Ford-Fulkerson.&lt;/p&gt;
&lt;p&gt;Các phần tiếp theo bao quát tìm kiếm chuỗi, nén và mã hóa dữ liệu (Huffman, LZ, biến đổi Fourier, nén ảnh JPEG), tối ưu hóa (Simplex, Simulated Annealing), học máy và khoa học dữ liệu, cùng các thuật toán bảo mật và mật mã. Cuối bài là mục tài liệu luyện phỏng vấn như &amp;ldquo;14 Patterns to Ace Any Coding Interview&amp;rdquo; và &amp;ldquo;5 Simple Steps for Solving Dynamic Programming Problems&amp;rdquo;, rất hữu ích cho các bạn mới vào nghề đang chuẩn bị phỏng vấn.&lt;/p&gt;
&lt;h2 id="bonus-vài-ảnh-hay-ho-đến-từ-bytebytego"&gt;Bonus: Vài ảnh hay ho đến từ &lt;a class="link" href="https://bytebytego.com/" target="_blank" rel="noopener"
&gt;ByteByteGo&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/81074d22-5821-4aec-bb2d-0a099d06b6ac_1600x840.png"
loading="lazy"
alt="3 Steps to Master Your Software"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/67c39b9a-9a91-4e57-9e24-7714b4f806dd_1280x1349.gif"
loading="lazy"
alt="The Ultimate Software Architect Roadmap"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/fb1b1cd1-eac3-4b66-a391-9ec73f6c37f3_1280x1502.gif"
loading="lazy"
alt="How Two-factor Authentication (2FA) Works?"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/3efae3ad-8c45-4fb2-a79f-6b3387b0751e_1280x1601.gif"
loading="lazy"
alt="How Amazon S3 Works?"
&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được viết lại bởi Claude Code với Opus 5.5 vào ngày 27/09/2026.&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>