idea安裝好熱加載插件 JRebel,啓動後報錯java.lang.OutOfMemoryError: PermGen space解決方法
報錯緣由是由於內存溢出了,也就是內存不足,方法就是增長內存,添加以下配置:
java
參數解釋:
-Xms,表示程序啓動時,JVM 堆的初始化最小尺寸參數;
-Xmx,表示程序啓動時,JVM 堆的初始化最大尺寸參數;
-XX:PermSize,表示程序啓動時,JVM 方法區的初始化最小尺寸參數;
-XX:MaxPermSize,表示程序啓動時,JVM 方法區的初始化最大尺寸參數。安全
激活JRebel
生成 GUID 的網址:https://www.guidgen.com/網絡
用這個網址 + 生成的 GUID 激活數據結構
https://jrebel.qekang.com/
例如:jvm
https://jrebel.qekang.com/cb2546bb-9d43-4115-bf4b-10539349efed
File -> Settings -> JRebel -> [Work offline]按鈕
既然用了這個熱加載,就瞭解一下這個熱加載原理ide
java的類加載過程
一個java類文件到虛擬機裏的對象,要通過以下過程:
首先咱們編寫好了的java源代碼經過java編譯器,將java源代碼文件編譯成class字節碼,類加載器讀取class字節碼,再將類轉化爲實例,對實例newInstance就能夠生成對象。
類加載器ClassLoader功能,也就是將class字節碼轉換爲類的實例。在java應用中,全部的實例都是由類加載器,加載而來。通常在系統中,類的加載都是由系統自帶的類加載器完成,並且對於同一個全限定名的java類(如com.csiar.soc.HelloWorld),只能被加載一次,並且沒法被卸載。工具
加載class字節碼的工做是由類加載器實例去實現的,類加載器支持經過文件目錄,jar,zip,網絡等多種途徑,加載class字節碼文件。
JVM啓動後就默認有三個類加載器實例,負責去加載不一樣位置的class。
1.核心類庫加載器 BootStrap ClassLoader,負責加載jdk安裝目錄下lib文件夾裏面的jar包,咱們的String.class,System.class這些類都放在這個目錄下面,啓動jvm就會去加載,必不可少。
2.拓展類庫加載器 Extension ClassLoader,負責加載jdk安裝目錄下lib/ext文件夾裏面的jar包,這裏面是一些jdk的拓展jar包,好比zipfs.jar這樣的包或工具類。拓展的意思就是在某些狀況下,這些jar包不加載也不影響jvm工做。
3.應用程序代碼加載器 Application ClassLoader,負責加載咱們本身寫的程序代碼,經過java命令 -cp 或者 -classpath告訴jvm咱們的代碼class存放位置。若是咱們的程序是jar包運行,你能夠在jar包 META-INF目錄MANIFEST.MF文件裏面看到一個Class-Path: .配置,這就是指定代碼位置的。佈局
java類加載的階段
加載階段
找到類的靜態存儲結構,並加載到虛擬機裏面,而後轉換成方法區的運行時數據結構,生成class對象,加載階段,用戶能夠自定義類加載器參與進來。
驗證階段
主要確保字節碼安全的,確保不會對虛擬機安全形成危害,能夠經過JVM啓動參數來禁用一些驗證,但不推薦修改設置,參數禁用可能會對虛擬機安全形成一些危害。
準備階段
肯定內存佈局,初始化內存變量,注意點:賦初始值,不會執行程序本身定義的賦值操做,好比定義了一個私有變量:private static int count = 12,在準備階段並非把count初始爲了12,這裏是會賦初始值,int初始值爲0,因此會把這私有靜態變量賦值爲0,而不是12。
解析階段
這個階段主要是將符號引用變爲直接引用。
初始化階段
調用程序自定義的代碼。好比private static int count = 12, count在本階段將會被初始化爲12,而不是以前準備階段的0,初始化階段會生成clean int 方法,這個方法由編譯器自動收集類中的全部類變量的賦值、動做和靜態語句塊中的語句合併,同一個類加載器中,只會將一個類型初始化一次。post
Java虛擬機沒有強制約束何時開始初始化階段,但規定了5種狀況必須當即初始化,固然這以前的幾種操做都是已經運行了的。5種狀況以下:ui
1.遇到new、 get static 、post static、 invoke static這四條字節碼指令的時候,若是類沒有初始化,須要觸發初始化,注意的是final修飾的類,會在編譯期的時候,將結果放在常量池,即便調用也不會觸發初始化,由於final修飾的是常量,會把常量放在常量池,調用常量不會觸發初始化這個階段。
2.使用java.long.reflect包裏方法,即對類進行反射調用的時候,若是類沒初始化的話,須要初始化。
3.當初始化一個子類的時候,若是父類尚未初始化,須要先初始化父類,再初始化子類。
4.虛擬機啓動的時候,用戶制定一個要執行的主類,虛擬機會先初始化這個主類,例子:咱們寫的java程序,在某一個類裏面寫了一個main方法,經過運行這個main方法啓動這個程序,虛擬機會先初始化這個main方法所在的類。
5.使用jdk1.7動態語言支持的時候,若是java.lang.invoke.methondhandler類實例解析的最後結果是ref_getstatic、ref_putstatic、ref_invokestatic方法句柄的時候,若是句柄對應的類沒有初始化,那就須要先初始化句柄對應的類。
1.由AppClass Loader(系統類加載器)開始加載指定的類;
2.類加載器將加載任務交給其父類,若是其父類找不到,再交給本身去加載(即雙親委派);
3.Bootstrap Loader (啓動類加載器)是最頂級的類加載器。
熱加載的實現原理主要依賴java的類加載機制,在實現方式能夠歸納爲在容器啓動的時候起一個後臺線程,定時的檢測類文件的時間戳變化,若是類的時間戳變化了,則將類從新載入。
對比反射機制,反射是在運行時獲取類信息,經過動態的調用來改變程序行爲; 熱加載則是在運行時經過從新加載改變類信息,直接改變程序行爲。