虚拟机、类在内存中干了什么?这是对程序优化的前提知识吧!想写个程序优化的系列文章,主要写的通俗些让人一看就懂,当然严谨性就降低了。毕竟我不太可能开发虚拟机嘛!如果要自己研究还是看《深入理解Java虚拟机》这本神书吧。吐三升血来推荐这本书,这本书把.class文件、虚拟机构造、如何执行、如何优化讲的淋漓尽致。
运行时数据区域(JAVA虚拟机在内存中划分的几个区域):
你想想啊!我们写的.java文件编译后形成.class文件。java中的类名A、方法名、常量CONSTANT和方法中的逻辑会全部映射到.class文件中,而加载.class文件到虚拟机内存中,内存中肯定也会存储这些信息。那么内存中是在那里存储这些信息呢? 实际上这个过程就是层层筛检,将人类易理解的冗余信息---》到机器能理解的极端简洁信息0101。
示例:
public class A{ private int a = 3; public static final int CONSTANT = 32; }
public class B{ static{ System.out.println(A.CONSTANT); } }
1.堆(heap)
占内存最大的一块。存储信息
a)类对象的字段值:如A类对象a属性的值3。(对象不同而字段数值不同的信息,所以CONSTANT不在这里存储,因为所有的A类对象都只有一个值32)
b)方法区中存储该类不变信息的地址(A类对象不变化的信息是:字段名称a,类名称A,修饰符private。你有N个对象,类的字段名称也不会变嘛)
2.方法区(Method Area)
存储信息:
a)类不变信息:字段名称a,类名称A,修饰符private
b)运行时常量池(Runtime Constant Pool)用于存储编译期间生成的符号引用、字面常量。 (比如说.class文件字节码中用#1代表CONSTANT属性值3)
//-----------------------------以上是线程公有的-------------------------
3.JAVA虚拟机栈
栈中有栈帧(Stack Heap),存储局部变量表、操作栈、动态链接、方法出口等信息
4.本地方法栈
和虚拟机栈类似,只是描述的是修饰符为native的本地方法。
5.直接内存
6.程序计数器
记录程序进行到字节码行数。
要优化,就得先知道类在内存中怎么运行的。
加载(Loading)--》验证(Verification)--》准备(Preparation)---》解析(Resolution)--》初始化(Initiation)---》使用(Using)----》卸载(Unloading)。 其中标黄的验证---》准备---》解析被称为连接(Linking)。
(Android自带的proGuard有个功能叫做preVerification,Android上这个功能是被屏蔽的。在Java Micro Edition 和 Java 6把验证给分开了,在编译期间就可以进行预验证(preVerification))
其中加载和连接阶段是不会执行我们写的代码的(除非你重写类加载器),初始化阶段才开始。
加载:
1)通过类的全限定名(包名+类名)获取此类的二进制文件
2)类的静态存储结构(.class文件中描绘的方法、字段、修饰符)转换为 方法区 运行时数据结构
3)在Java堆中生成一个代表改类的java.lang.Class对象,作为方法区的访问入口
JAVA常量static加上final,则编译期间直接用32代替CONSTANT。换句话说在B的运行中没有加载A类,来读取CONSTANT变量,而是引用了B自身的常量池CONSTANT。这样就省内存,因为没有加载A类。
在java字节码中:带final
原文地址:http://blog.csdn.net/zhjali123/article/details/43795713