本文摘自: http://blog.163.com/guixl_001/blog/static/41764104201082961141664/,並稍加整理。ui
package demo; public class Volcano { public static void main(String[] args) { Lava lava = new Lava(); lava.flow(); } } class Lava { private int speed = 5; void flow() { speed++; System.out.println(speed); } }
下面咱們描述一下main()方法的第一條指令的字節碼是如何被執行 的。不一樣的JVM有不一樣的實現,這只是其中的一種實現。指針
爲了運行這個程序,咱們會以某種方式把「demo.Volcano"傳給JVM,JVM找到並讀取這個類文件;它從類文件提取類型信息並寫入方法區,經過解析方法區中的字節碼激活main()方法。 在執行時,JVM保持了一個指向當前類Volcano的常量池的指針。code
注意,JVM在尚未加載Lava類的時候就已經開始執行了。正像大多數的 JVM同樣,不是等全部類都加載了之後纔開始執行,而是隻會在須要的時候作加載。對象
main()的第一條指令告知JVM對位於常量池中第一項的類作初始化:JVM經過指向Volcano常量池的指針找到第一項,發現是一個對Lava類的符號引用,而後它就檢查方法區看Lava類是否已被加載。blog
這個符號引用就是類Lava類的完整有效名「demo.Lava」, 當JVM發現尚未加載過名稱爲「demo.Lava」的類,它就開始查找並加載類文件"demo.Lava.class",從類文件中抽取類型信息並寫入方法區。get
而後,JVM以一個直接指向方法區Lava類的指針替換了常量池第一項的符號引用,以後就能夠用這個指針快速的找到Lava類了。而這個替換過程也稱爲常量池解析(constant pool resolution)。io
終於,JVM開始爲新的Lava對象分配空間了:JVM經過指向Lava類的指針(剛纔指向volcano常量池第一項的指針)獲得一個Lava對象究竟須要多少空間。 一旦JVM知道了一個Lava對象所要的空間,它就在堆上分配這個空間併爲實例變量初始化正確的值。class
當把新生成的Lava對象的引用壓到棧中,第一條指令也結束了。下面的指令會用這個引用激活Lava對象的flow()方法。gui