1. 程式人生 > >從AndroidStudio的啟動引數開始,瞭解一下JVM的一些東西(記憶體使用,JIT等)

從AndroidStudio的啟動引數開始,瞭解一下JVM的一些東西(記憶體使用,JIT等)

如果你使用AndroidStudio經常覺得很卡,那有可能是因為系統給AS分配的記憶體不夠的原因。開啟/Applications/Android Studio.app/Contents/bin/studio.vmoptions (Mac),可以看到有以下配置:

-Xms128m  
-Xmx750m  
-XX:MaxPermSize=350m  
-XX:ReservedCodeCacheSize=96m  
-XX:+UseCompressedOops  

這些引數分別是什麼意思呢?

-XMS128M

The -Xms option sets the initial and minimum Java heap size. The Java heap (the “heap”) is the part of the memory where blocks of memory are allocated to objects and freed during garbage collection.

就是JVM啟動的起始堆記憶體,堆記憶體是分配給物件的記憶體。這裡我把它改成了512m

-XMX750M

This option sets the maximum Java heap size.

也就是AndroidStudio能使用的最大heap記憶體,這裡我改成了2048m

這兩個引數都是-X開頭的,表示非標準的引數。什麼叫非標準的呢?我們知道JVM有很多個實現,Oracle的,OpenJDK等等,這裡的-X引數,是Oracle的JVM實現使用的,OpenJDK不一定能使用,也就是沒有將這些引數標準化,讓所有的JVM實現都能使用。

-XX:MAXPERMSIZE=350M

這個引數指定最大的Permanent generation大小。
根據

oracle的文件

Permanent Generation (non-heap): The pool containing all the reflective data of the virtual machine itself, such as class and method objects. With Java VMs that use class data sharing, this generation is divided into read-only and read-write areas.

可知,Permanent Generation也是一塊記憶體區域,跟heap不同,它裡面存放的事類本身(不是物件),以及方法,一些固定的字串等等。更多關於

Permanent Generation

-XX:RESERVEDCODECACHESIZE=90M

ReservedCodeCacheSize (and InitialCodeCacheSize) is an option for the (just-in-time) compiler of the Java Hotspot VM. Basically it sets the maximum size for the compiler's code cache.

設定JIT java compiler在compile的時候的最大程式碼快取。簡單地說就是JIT(Just In Time)編譯器在編譯程式碼的時候,需要快取一些東西,這個引數指定最多能使用多大記憶體來快取這些東西。
什麼叫JIT呢?看wikipedia的解釋

In computing, just-in-time compilation (JIT), also known as dynamic translation, is compilation done during execution of a program – at run time – rather than prior to execution.Most often this consists of translation to machine code, which is then executed directly, but can also refer to translation to another format. JIT compilation is a combination of the two traditional approaches to translation to machine code – ahead-of-time compilation (AOT), and interpretation – and combines some advantages and drawbacks of both.[1] Roughly, JIT compilation combines the speed of compiled code with the flexibility of interpretation, with the overhead of an interpreter and the additional overhead of compiling (not just interpreting). JIT compilation is a form of dynamic compilation, and allows adaptive optimization such as dynamic recompilation – thus in principle JIT compilation can yield faster execution than static compilation. Interpretation and JIT compilation are particularly suited for dynamic programming languages, as the runtime system can handle late-bound data types and enforce security guarantees.

我們知道程式語言分兩種: - 編譯型,先將人寫的程式碼整個編譯成組合語言或機器語言,一條一條程式碼然後執行。 - 解釋型,不需要編譯,將人寫的程式碼一條一條拿過來一次執行,先取一條,執行,完了再取下一條,然後在執行。

而對於Java來說,這個情況就比較特殊了,因為在Java這裡,JVM先是將Java程式碼整個編譯成bytecode,然後在JVM內部再一條一條執行bytecode程式碼。你說它是編譯型的吧,bytecode又不用編譯成機器程式碼,二是一條條bytecode一次執行。你說它是解釋型的吧,它又有一個編譯的過程。對於Java到底是編譯型還是解釋型到現在也沒有一個定論。不過,我們還是可以探討一下Java的JIT編譯技術。
剛剛說了,在bytecode層面,程式碼是解釋執行的。解釋型的語言會比較慢,因為它沒有辦法根據上下文對程式碼進行優化。而編譯型的語言則可以進行優化。Java的JIT技術,就是在bytecode解釋執行的時候,它不一定是一條條解釋執行的,二是取一段程式碼,編譯成機器程式碼,然後執行,這樣的話就有了上下文,可以對程式碼進行優化了,所以執行速度也會更快。
可見,JIT技術結合了編譯型(速度更快)和解釋型語言(程式碼更靈活)二者的優勢。對於動態語言的執行來說,是一個非常大的優勢。

-XX:+USECOMPRESSEDOOPS

這個引數允許系統將程式碼裡面的引用(reference)型別用32位儲存,同時卻能夠讓引用能夠使用64位的記憶體大小。
我們知道現代的機器基本都是64位的,在這種情況下,Java程式碼裡面的reference型別也變成了用64位來儲存,這就導致了兩個問題:
1. 64位比32為更大,佔的記憶體更多,這是顯然的,當然這個問題在整個程式看來根本不顯然,因為哪怕系統同時有1000個引用存在,那多出來的記憶體也就4M,這個不重要,因為現在手機都動不動好幾個G,大型伺服器就更加不用說了。更重要的是第二點。 2. 相對於記憶體,CPU的cache就小的可憐了,當reference從32bit變成64bit時,cache裡面能存放的reference數量就頓時少了很多。所以64bit的reference對cache是個大問題,於是就有了這個選項,可以允許系統用32bit來儲存reference,讓cache裡面能存放更多的reference,同時又不影響reference的取址範圍。至於他們是怎麼做到的,我就不得而知了。。。

以上三個引數是以-XX開頭的,根據Oracle的說明

Options that are specified with -XX are not stable and are subject to change without notice.

寫文章就是一個挖坑的過程,這篇文章依然後很多坑沒有填滿,而且如果要繼續挖,也可以挖出很多坑。由於能力有限,我還是就此打住吧。

最後貼上我自己的配置,僅供參考,我的電腦是記憶體是8G(I know, 弱爆了對吧?):

-Xms512m  
-Xmx2048m  
-XX:MaxPermSize=1024m  
-XX:ReservedCodeCacheSize=512m  
-XX:+UseCompressedOops