JVM運行時數據區深度解析

💾 JVM運行時數據區深度解析


文章目錄

  • 💾 JVM運行時數據區深度解析
    • 🎯 引言
    • 📚 方法區
      • 📋 方法區存儲內容
      • 🔄 從永久代到元空間的演進
        • 永久代時期(JDK 8之前)
        • 元空間時期(JDK 8及以后)
    • 🏠 堆內存
      • 🏗? 堆內存的分代設計
      • 🌱 新生代中的 Eden 區、Survivor 區
        • 內存分配策略
        • 對象晉升過程
      • 🗑? 堆內存的垃圾回收機制
        • 垃圾回收類型
    • 📚 虛擬機棧
      • 🏗? 棧幀結構
        • 棧幀組件詳解
      • ?? 棧溢出異常分析與解決
        • 棧溢出的原因
        • 解決方案
    • 🔗 本地方法棧
      • 🌐 本地方法棧與 Native 方法的關系
      • 🔍 本地方法棧常見問題排查
        • 常見問題類型
    • 📍 程序計數器
      • ?? 程序計數器的功能與作用
        • 程序計數器的特點
      • 🧵 多線程與程序計數器
        • 線程切換與程序計數器
    • 🔄 運行時數據區協作機制
      • 組件間的協作流程
      • 內存分配示例
    • 🚀 性能優化建議
      • 內存調優參數
      • 監控和診斷工具
      • 最佳實踐
    • 📊 總結
      • 核心要點回顧
      • 學習建議


🎯 引言

JVM運行時數據區是Java程序執行的核心基礎設施,理解其內部結構和工作機制對于Java開發者來說至關重要。本文將深入解析JVM運行時數據區的五大組成部分,幫助您全面掌握JVM內存管理的精髓。

📚 方法區

📋 方法區存儲內容

方法區(Method Area)是JVM中所有線程共享的內存區域,主要存儲以下內容:

存儲內容描述示例
類信息類的版本、字段、方法、接口等元數據Class對象、方法簽名
常量池字面量和符號引用字符串常量、類名、方法名
靜態變量類級別的變量static修飾的變量
即時編譯器編譯后的代碼JIT編譯的機器碼熱點代碼的本地代碼
public class MethodAreaExample {// 靜態變量存儲在方法區private static final String CONSTANT = "Hello World";private static int counter = 0;// 方法信息存儲在方法區public static void incrementCounter() {counter++;}// 類信息存儲在方法區public void instanceMethod() {System.out.println("Instance method called");}
}

🔄 從永久代到元空間的演進

永久代時期(JDK 8之前)
JVM堆內存
新生代
老年代
永久代
類元數據
常量池
靜態變量

永久代的問題:

  • 固定大小限制,容易出現OutOfMemoryError
  • 垃圾回收效率低
  • 與堆內存共享空間,影響整體性能
元空間時期(JDK 8及以后)
JVM內存
堆內存
元空間-本地內存
新生代
老年代
類元數據
方法信息
常量池

元空間的優勢:

  • 使用本地內存,大小僅受系統內存限制
  • 自動擴展,減少OOM風險
  • 垃圾回收更高效
# JDK 8之前的永久代配置
-XX:PermSize=128m
-XX:MaxPermSize=256m# JDK 8及以后的元空間配置
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=256m

🏠 堆內存

🏗? 堆內存的分代設計

堆內存是JVM中最大的內存區域,采用分代收集理論進行設計:

堆內存
新生代 Young Generation
老年代 Old Generation
Eden區
Survivor0區
Survivor1區

🌱 新生代中的 Eden 區、Survivor 區

內存分配策略
區域比例作用特點
Eden區80%新對象分配分配速度快,回收頻繁
Survivor0區10%存活對象暫存與S1區輪換使用
Survivor1區10%存活對象暫存與S0區輪換使用
public class HeapMemoryExample {public static void main(String[] args) {// 新對象在Eden區分配List<String> list = new ArrayList<>();for (int i = 0; i < 1000000; i++) {// 大量對象創建,觸發Minor GClist.add("Object " + i);if (i % 100000 == 0) {System.gc(); // 建議進行垃圾回收}}}
}
對象晉升過程
Eden區Survivor0Survivor1老年代第一次GC存活對象第二次GC存活對象第三次GC存活對象年齡計數器+1年齡達到閾值(默認15)或Survivor區空間不足Eden區Survivor0Survivor1老年代

🗑? 堆內存的垃圾回收機制

垃圾回收類型
GC類型作用區域觸發條件特點
Minor GC新生代Eden區滿頻繁,速度快
Major GC老年代老年代滿較少,速度慢
Full GC整個堆系統調用或內存不足最慢,影響性能
// 監控GC的示例代碼
public class GCMonitor {public static void main(String[] args) {// 獲取垃圾回收器信息List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();for (GarbageCollectorMXBean gcBean : gcBeans) {System.out.println("GC名稱: " + gcBean.getName());System.out.println("GC次數: " + gcBean.getCollectionCount());System.out.println("GC時間: " + gcBean.getCollectionTime() + "ms");}// 獲取內存使用情況MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();System.out.println("堆內存使用情況:");System.out.println("初始大小: " + heapUsage.getInit() / 1024 / 1024 + "MB");System.out.println("已使用: " + heapUsage.getUsed() / 1024 / 1024 + "MB");System.out.println("最大大小: " + heapUsage.getMax() / 1024 / 1024 + "MB");}
}

📚 虛擬機棧

🏗? 棧幀結構

虛擬機棧是線程私有的內存區域,每個方法調用都會創建一個棧幀:

虛擬機棧
棧幀1 - 當前方法
棧幀2 - 調用者方法
棧幀3 - 更早的方法
局部變量表
操作數棧
動態鏈接
方法返回地址
棧幀組件詳解
組件作用存儲內容
局部變量表存儲方法參數和局部變量基本類型、對象引用
操作數棧方法執行時的操作數存儲計算過程中的臨時數據
動態鏈接運行時常量池的引用方法調用的符號引用
方法返回地址方法執行完成后的返回位置調用者的程序計數器值
public class StackFrameExample {private int instanceVar = 10;public int calculate(int a, int b) {// 局部變量表: a, b, resultint result = a + b + instanceVar;// 操作數棧用于計算過程// 1. 加載a到操作數棧// 2. 加載b到操作數棧// 3. 執行加法操作// 4. 加載instanceVar到操作數棧// 5. 執行加法操作// 6. 存儲結果到局部變量表return result; // 方法返回地址指向調用者}public static void main(String[] args) {StackFrameExample example = new StackFrameExample();int result = example.calculate(5, 3);System.out.println("Result: " + result);}
}

?? 棧溢出異常分析與解決

棧溢出的原因
  1. 遞歸調用過深
  2. 方法調用鏈過長
  3. 棧空間設置過小
public class StackOverflowExample {private static int count = 0;// 無限遞歸導致棧溢出public static void recursiveMethod() {count++;System.out.println("遞歸調用次數: " + count);recursiveMethod(); // StackOverflowError}// 正確的遞歸實現public static int factorial(int n) {if (n <= 1) {return 1; // 遞歸終止條件}return n * factorial(n - 1);}// 使用迭代替代遞歸public static int factorialIterative(int n) {int result = 1;for (int i = 2; i <= n; i++) {result *= i;}return result;}
}
解決方案
解決方法描述示例
增加棧大小使用-Xss參數-Xss2m
優化遞歸算法添加終止條件見上述代碼
使用迭代替代遞歸實現見factorialIterative方法
尾遞歸優化編譯器優化某些JVM支持

🔗 本地方法棧

🌐 本地方法棧與 Native 方法的關系

本地方法棧為Native方法服務,與虛擬機棧類似但用于本地方法調用:

Java方法
虛擬機棧
Native方法
本地方法棧
棧幀
本地棧幀
局部變量表
操作數棧
本地變量
本地方法信息
public class NativeMethodExample {// 聲明本地方法public native void nativeMethod();public native int nativeCalculation(int a, int b);// 加載本地庫static {System.loadLibrary("nativelib");}// 使用系統提供的本地方法public void systemNativeExample() {// System.currentTimeMillis() 是本地方法long currentTime = System.currentTimeMillis();// System.arraycopy() 也是本地方法int[] source = {1, 2, 3, 4, 5};int[] dest = new int[5];System.arraycopy(source, 0, dest, 0, 5);System.out.println("當前時間: " + currentTime);System.out.println("復制的數組: " + Arrays.toString(dest));}
}

🔍 本地方法棧常見問題排查

常見問題類型
問題類型癥狀排查方法
本地庫加載失敗UnsatisfiedLinkError檢查庫路徑和依賴
本地方法棧溢出StackOverflowError檢查本地方法調用深度
內存泄漏內存持續增長使用內存分析工具
JNI錯誤程序崩潰檢查JNI代碼實現
public class NativeMethodTroubleshooting {public static void checkNativeLibrary() {try {// 檢查本地庫是否可以加載System.loadLibrary("example");System.out.println("本地庫加載成功");} catch (UnsatisfiedLinkError e) {System.err.println("本地庫加載失敗: " + e.getMessage());// 輸出庫搜索路徑String libraryPath = System.getProperty("java.library.path");System.out.println("庫搜索路徑: " + libraryPath);}}public static void monitorNativeMemory() {// 監控本地內存使用MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();System.out.println("非堆內存使用情況:");System.out.println("已使用: " + nonHeapUsage.getUsed() / 1024 / 1024 + "MB");System.out.println("最大值: " + nonHeapUsage.getMax() / 1024 / 1024 + "MB");}
}

📍 程序計數器

?? 程序計數器的功能與作用

程序計數器(PC Register)是JVM中最小的內存區域:

程序計數器
存儲當前執行指令地址
線程私有
不會發生OutOfMemoryError
Java方法: 字節碼指令地址
Native方法: undefined
程序計數器的特點
特點描述意義
線程私有每個線程都有獨立的PC支持多線程執行
存儲指令地址當前執行的字節碼指令位置控制程序執行流程
無內存異常唯一不會OOM的區域穩定可靠
大小固定存儲一個地址值內存開銷極小

🧵 多線程與程序計數器

public class ProgramCounterExample {private static volatile boolean running = true;private static int counter = 0;public static void main(String[] args) throws InterruptedException {// 創建多個線程,每個線程都有獨立的程序計數器Thread thread1 = new Thread(() -> {while (running) {counter++;// 每個線程的程序計數器獨立跟蹤執行位置if (counter % 1000000 == 0) {System.out.println("Thread1 - Counter: " + counter);}}}, "Thread-1");Thread thread2 = new Thread(() -> {while (running) {counter++;// 程序計數器確保線程切換后能正確恢復執行if (counter % 1000000 == 0) {System.out.println("Thread2 - Counter: " + counter);}}}, "Thread-2");thread1.start();thread2.start();// 運行5秒后停止Thread.sleep(5000);running = false;thread1.join();thread2.join();System.out.println("最終計數: " + counter);}
}
線程切換與程序計數器
操作系統線程1線程2PC寄存器1PC寄存器2分配CPU時間片更新指令地址執行字節碼指令時間片結束保存當前指令地址分配CPU時間片讀取指令地址從保存位置繼續執行時間片結束保存當前指令地址重新分配時間片恢復指令地址從中斷位置繼續執行操作系統線程1線程2PC寄存器1PC寄存器2

🔄 運行時數據區協作機制

組件間的協作流程

方法調用
程序計數器更新
虛擬機棧創建棧幀
局部變量表初始化
從堆內存加載對象
方法區獲取類信息
操作數棧執行計算
動態鏈接解析方法
是否Native方法?
本地方法棧處理
繼續字節碼執行
方法返回
棧幀銷毀
程序計數器更新

內存分配示例

public class MemoryAllocationExample {// 靜態變量 - 存儲在方法區private static String staticVar = "Static Variable";// 實例變量 - 存儲在堆內存private String instanceVar = "Instance Variable";public void demonstrateMemoryAllocation() {// 局部變量 - 存儲在虛擬機棧的局部變量表int localVar = 42;String localString = "Local String";// 對象創建 - 在堆內存分配List<String> list = new ArrayList<>();// 方法調用 - 在虛擬機棧創建新棧幀processData(localVar, localString);// 調用本地方法 - 使用本地方法棧long currentTime = System.currentTimeMillis();System.out.println("演示完成,當前時間: " + currentTime);}private void processData(int value, String text) {// 新的棧幀創建,有自己的局部變量表String processedText = text + " - Processed";int processedValue = value * 2;// 程序計數器跟蹤當前執行的字節碼指令System.out.println("處理結果: " + processedText + ", " + processedValue);}public static void main(String[] args) {// main方法的棧幀MemoryAllocationExample example = new MemoryAllocationExample();example.demonstrateMemoryAllocation();}
}

🚀 性能優化建議

內存調優參數

參數類型參數說明推薦值
堆內存-Xms初始堆大小物理內存的1/4
堆內存-Xmx最大堆大小物理內存的1/2
新生代-Xmn新生代大小堆內存的1/3
棧內存-Xss棧大小1-2MB
元空間-XX:MetaspaceSize初始元空間大小128MB
元空間-XX:MaxMetaspaceSize最大元空間大小256MB

監控和診斷工具

public class MemoryMonitoring {public static void printMemoryInfo() {Runtime runtime = Runtime.getRuntime();long maxMemory = runtime.maxMemory();long totalMemory = runtime.totalMemory();long freeMemory = runtime.freeMemory();long usedMemory = totalMemory - freeMemory;System.out.println("=== JVM內存信息 ===");System.out.println("最大內存: " + formatBytes(maxMemory));System.out.println("總內存: " + formatBytes(totalMemory));System.out.println("空閑內存: " + formatBytes(freeMemory));System.out.println("已使用內存: " + formatBytes(usedMemory));System.out.println("內存使用率: " + String.format("%.2f%%", (double) usedMemory / maxMemory * 100));}private static String formatBytes(long bytes) {return String.format("%.2f MB", bytes / 1024.0 / 1024.0);}public static void main(String[] args) {printMemoryInfo();// 創建一些對象來觀察內存變化List<String> list = new ArrayList<>();for (int i = 0; i < 100000; i++) {list.add("String " + i);}System.out.println("\n創建對象后:");printMemoryInfo();// 建議垃圾回收System.gc();System.out.println("\n垃圾回收后:");printMemoryInfo();}
}

最佳實踐

  1. 合理設置內存參數
# 生產環境推薦配置
-Xms4g -Xmx4g -Xmn1g -Xss1m
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
  1. 避免內存泄漏
public class MemoryLeakPrevention {// 避免靜態集合持有大量對象private static final Map<String, Object> cache = new ConcurrentHashMap<>();public void addToCache(String key, Object value) {// 設置緩存大小限制if (cache.size() > 10000) {cache.clear(); // 或使用LRU策略}cache.put(key, value);}// 及時關閉資源public void processFile(String filename) {try (FileInputStream fis = new FileInputStream(filename);BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {String line;while ((line = reader.readLine()) != null) {// 處理文件內容}} catch (IOException e) {e.printStackTrace();}// 資源自動關閉,避免內存泄漏}
}

📊 總結

核心要點回顧

內存區域線程共享主要作用常見問題優化建議
方法區/元空間存儲類信息、常量MetaspaceOOM合理設置元空間大小
堆內存對象存儲內存泄漏、GC頻繁調優GC參數
虛擬機棧方法調用棧溢出控制遞歸深度
本地方法棧Native方法調用本地庫問題檢查JNI實現
程序計數器指令地址無需優化

學習建議

  1. 理論與實踐結合:通過編寫測試代碼驗證理論知識
  2. 使用監控工具:熟練掌握JVisualVM、JProfiler等工具
  3. 關注性能指標:監控GC頻率、內存使用率等關鍵指標
  4. 持續學習:跟進JVM新特性和優化技術

如果這篇博客對您有幫助,歡迎點贊、評論、收藏,您的支持是我持續創作的動力!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88323.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88323.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88323.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

.NET nupkg包的深度解析與安全防護指南

在.NET開發領域&#xff0c;nupkg包是開發者們不可或缺的工具。它不僅是代碼分發和資源共享的核心載體&#xff0c;還貫穿了開發、構建、部署的全流程。今天&#xff0c;我們將深入探討nupkg包的核心功能、打包發布流程以及安全防護措施&#xff0c;幫助你在.NET開發中更加得心…

Cursor 快速入門指南:從安裝到核心功能

引言 Cursor 是一款融合 AI 能力的現代代碼編輯器&#xff0c;旨在提升開發者的編碼效率。本文將帶您從零開始&#xff0c;快速掌握 Cursor 的完整使用流程 - 包括安裝配置、項目初始化以及核心 AI 功能的應用。 正文 1. 安裝與初始配置 1.1 下載與安裝 Cursor 支持跨平臺…

自然語言處理中probe探測是什么意思。

文章目錄&#x1f539; 1. 英文單詞的基本含義&#xff08;動詞 & 名詞&#xff09;? 作為動詞&#xff08;to probe&#xff09;&#xff1a;? 作為名詞&#xff08;a probe&#xff09;&#xff1a;&#x1f539; 2. 不同領域的具體含義&#x1f539; 3. 在機器學習/NL…

【記錄】Ubuntu掛載home文件夾到磁盤

問題描述 服務器裝好后,home文件夾一般存放各個用戶的文件,默認的存儲磁盤為系統磁盤,一般比較小,可能幾百G,這對于服務器來講,相當小了,所以需要對home文件夾進行重新調整。 我之前的博文 點擊進入 相關配置在重啟機器后,磁盤配置自動失效,即配置好后,home在大的磁…

【注意避坑】基于Spring AI 開發本地天氣 mcp server,通義靈碼測試MCP server連接不穩定,cherry studio連接報錯

springboot 版本&#xff1a; 3.5.4 cherry studio版本&#xff1a;1.4.7 通義靈碼版本&#xff1a; 2.5.13 文章目錄 問題描述&#xff1a;1. 通義靈碼添加mcp server &#xff0c;配置測試2. cherry studio工具添加mcp server &#xff0c;配置測試 項目源代碼&#xff1a;解…

Paimon LSM Tree Compaction 策略

壓縮怎么進行的這里的操作都是KValue&#xff0c;內部有row kind&#xff0c;標記了刪除和插入MergeTreeCompactManager 是 Paimon 中 Merge-Tree 結構壓縮任務的總調度中心。它的核心職責就是監控文件的層級狀態&#xff08;Levels&#xff09;&#xff0c;并在合適的時機&…

小米路由器3C刷OpenWrt,更換系統/變磚恢復 指南

基礎篇看這里&#xff1a; 小米路由器3C如何安裝OpenWrt官方編譯的ROM - 嗶哩嗶哩 小米路由器 3C 刷入 Breed 和 OpenWrt - Snoopy1866 - 博客園 一、路由器注入 如果按照上面的文章&#xff0c; telnet、ftp一直連接失敗,那么可以嘗試看 這里&#xff1a; 獲取路由器root權…

Spring Boot 項目啟動時按需初始化加載數據

1、新建類&#xff0c;類上添加注解 Component &#xff0c;該類用于在項目啟動時處理數據加載任務&#xff1b; 2、該類實現 ApplicationRunner 接口&#xff0c;并重寫 run 方法&#xff1b; 3、在重寫的 run 方法里處理數據加載任務&#xff1b; 注意&#xff1a; 有定時加載…

MCP快速入門—快速構建自己的服務器

引言 隨著大語言模型(LLM)技術的快速發展&#xff0c;如何擴展其能力邊界成為開發者關注的重點。MCP(Model Capability Protocol)作為一種協議標準&#xff0c;允許開發者構建自定義服務器來增強LLM的功能。 正文內容 1. MCP核心概念與技術背景 MCP服務器主要提供三種能力類…

Vue 事件總線深度解析:從實現原理到工程實踐

在 Vue 組件通信體系中&#xff0c;事件總線&#xff08;Event Bus&#xff09;是處理非父子組件通信的輕量解決方案。本文將從技術實現細節、工程化實踐、內存管理等維度展開&#xff0c;結合源碼級分析與典型場景&#xff0c;帶你全面掌握這一核心技術點。?一、事件總線的技…

CMake Qt靜態庫中配置qrc并使用

CMake Qt序言環境代碼序言 看網上這資料較少&#xff0c;且我理解起來有歧義&#xff0c;特地補充 環境 CMake&#xff1a;3.29.2 Qt&#xff1a;5.15.2 MSVC&#xff1a;2022 IDE&#xff1a;QtCreator 代碼 方式一&#xff1a; 在CMakeLists.txt里&#xff0c;add_libr…

記錄一下:成功部署k8s集群(部分)

前提條件&#xff1a;安裝了containerd、docker 關閉了firewalld、selinux 配置了時間同步服務 chronyd 關閉swap分區等1、在控制節點、工作節點&#xff0c;安裝kubelet、kubeadm、kubectlyum install -y kubelet-1.26.0 kubeadm-1.26.0 kubectl-1.26.0 …

Idea如何解決包沖突

Idea如何解決包沖突1.Error信息&#xff1a;JAR列表。 在掃描期間跳過不需要的JAR可以縮短啟動時間和JSP編譯時間。SLF4J: Class path contains multiple SLF4J bindings.SLF4J: Found binding in [jar:file:/E:/javapojects/stww-v4-gjtwt-seal/target/stww--v4-platform-proj…

python 協程學習筆記

目錄 python 協程 通俗理解 Python 的 asyncio 協程&#xff0c;最擅長的是&#xff1a; 批量下載文件的例子&#xff1a; 協程的優勢&#xff1a; python 協程 通俗理解 def my_coroutine():print("開始")x yield 1print("拿到了&#xff1a;", x)yi…

【學習筆記】蒙特卡洛仿真與matlab實現

概述 20 世紀 40 年代&#xff0c;由于電子計算機的出現&#xff0c; 借助計算機可以實現大量的隨機抽樣試驗&#xff0c;為利用隨機試驗方法解決實際問題提供了便捷。 非常具代表性的例子是&#xff0c; 美國在第二次世界大戰期間研制原子彈的“曼哈頓計劃”中&#xff0c;為了…

HTTP/3.x協議詳解:基于QUIC的下一代Web傳輸協議

一、HTTP/3協議概述 HTTP/3是超文本傳輸協議&#xff08;HTTP&#xff09;的第三個正式版本&#xff0c;由IETF&#xff08;互聯網工程任務組&#xff09;于2022年正式標準化&#xff08;RFC 9114&#xff09;。其核心創新在于完全基于QUIC協議替代傳統TCP&#xff0c;結合UDP…

【SQL】使用UPDATE修改表字段的時候,遇到1054 或者1064的問題怎么辦?

我在使用python連接sql修改表格的時間字段的時候&#xff0c;遇到這樣一個問題&#xff1a;ProgrammingError: (pymysql.err.ProgrammingError) (1064, “You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the ri…

【字節跳動】數據挖掘面試題0013:怎么做男女二分類問題, 從抖音 app 提供的內容中。

文章大綱 ?? 一、問題定義與數據基礎數據源及預處理:?? 二、特征工程方案1. 文本特征2. 視覺特征3. 音頻與行為特征4. 上下文特征?? 三、模型選型與訓練1. 基礎模型對比2. 多模態融合模型3. 訓練技巧?? 四、評估與優化策略1. 評估指標2. 典型問題優化3. 算法偏差控制?…

HTTP請求走私漏洞

一、漏洞定義與核心原理HTTP請求走私&#xff08;HTTP Request Smuggling&#xff09;是一種利用前端服務器&#xff08;如代理、負載均衡器&#xff09;與后端服務器在解析HTTP請求時的不一致性&#xff0c;繞過安全機制并執行惡意操作的攻擊技術。其核心在于混淆請求邊界&…

Javaweb - 10.1 Servlet

目錄 Servlet 簡介 動態資源和靜態資源 Servlet 簡介 Servlet 開發流程 目標 開發過程 開發一個 web 類型的 module 開發一個 form 表單 開發一個 UserServlet 在 web..xml 為 userServlet 配置請求路徑 Edit Configurations 啟動項目 完&#xff01; Servlet 簡介…