JVM的基本结构图:javascript
由图可知,JVM的内存区域主要能够划分为5块:java
java.lang.StackOverFlowError
java.lang.OutOfMemoryError
和java栈的做用差很少,只不过是为JVM使用到的native方法(使用非Java语言实现的方法)服务的数组
OutOfMemoryError
的运行时数据区下面经过AppMain.java和Sample.java两块代码进一步说明多线程
//运行时, jvm把AppMain的信息都放入方法区
public class AppMain {
//main 方法自己放入方法区
public static void main(String[] args) {
//test1是引用,因此放到栈区里,Sample是自定义对象应该放到堆里面
Sample test1 = new Sample("测试1");
Sample test2 = new Sample("测试2");
test1.printName();
test2.printName();
}
}
复制代码
//运行时, jvm把Sample的信息都放入方法区
public class Sample {
//new Sample实例后, name 引用放入栈区里, name 对象放入堆里
private String name;
/** 构造方法 */
public Sample(String name) {
this.name = name;
}
/** 输出 */
//print方法自己放入方法区里
public void printName() {
System.out.println(name);
}
}
复制代码
启动虚拟机进程,程序从AppMain的开始,先从classpath中找到并读取AppMain.class二进制文件(编译后),而后把AppMain类的类信息和方法信息放入方法区,这个过程叫AppMain类的加载过程;jvm
Java虚拟机定位到方法区AppMain类中的main()方法的字节码,开始执行它的指令,第一条语句是:函数
Sample test1 = new Sample("测试1");
复制代码
接着Java虚拟机到方法区中查找Sample类的信息,没有找到,而后经过步骤1从新加载Sample类到方法区;测试
在堆中为Sample对象实例分配内存,这个实例持有指向方法区的Sample类的信息的引用(引用是指Sample类的信息在方法区中的内存地址)this
每个线程都有一个栈,栈里面的元素被称为栈帧,每当线程调用一个方法的时候就会往栈里压入一个新帧,这里的帧是用来存储方法的参数、局部变量和运算过程当中的临时数据。位于**“=”前的test1是一个在main()
方法中定义的变量,它是一个局部变量,所以,它被会添加到了执行main()
方法的主线程的java方法调用栈中,而“=”**将把这个test1变量指向堆区中的Sample实例,也就是说,它持有指向Sample实例的引用spa
接下来,JAVA虚拟机将继续执行后续指令,在堆区里继续建立另外一个Sample实例,而后依次执行它们的printName()
方法。当JAVA虚拟机执行test1.printName()
方法时,JAVA虚拟机根据局部变量test1持有的引用,定位到堆区中的Sample实例,再根据Sample实例持有的引用,定位到方法去中Sample类的类型信息,从而得到printName()
方法的字节码,接着执行printName()
方法包含的指令.net
一、Q: Java中的参数传递(传值呢?仍是传引用?)
A:
程序运行永远都是在栈中进行的,于是参数传递时,只存在传递基本类型和对象引用的问题,不会直接传递对象自己;
对象传递是引用值传递,原始类型数据传递是值传递; 实际上这个传入函数的值是对象引用的拷贝,即传递的是引用的地址值,因此仍是按值传递。
二、Q: Java对象的大小如何计算?
A:
Object obj = new Object();
复制代码
这样在程序中完成了一个java对象的声明,obj对象所占的空间为:
4byte(java栈中保存引用的所须要空间)+ 8byte(java堆中对象所需的空间) = 12byte
复制代码
全部的java非基本类型的对象都须要默认继承Object对象,所以不论什么样的java对象,其大小都必须是大于8byte
同时java对象大小是8的整数倍,所以obj对象的大小至少为16byte
对象引用类型分为强引用、软引用、弱引用和虚引用
一、强引用:声明对象时虚拟机生成的引用
Sample sample = new Sample();
复制代码
sample
为强引用,不会被垃圾回收
二、软引用:根据系统剩余内存来决定是否须要回收
换句话说,虚拟机在发生java.lang.OutOfMemoryError
时,确定是没有软引用存在的
三、弱引用:弱引用与软引用相似,但在进行垃圾回收时,是必定会被回收掉的
所以其生命周期只存在于一个垃圾回收周期内
四、虚引用虚引用并不会决定对象的生命周期。
若是一个对象仅持有虚引用,那么它就和没有任何引用同样,在任什么时候候均可能被垃圾回收器回收
虚引用主要用来跟踪对象被垃圾回收器回收的活动
参考地址: