浅谈JVM与内存分配
一.程序内存分配
初始内存分配
当一个程序准备运行时,它首先向java虚拟机要内存,但是java虚拟机本身没有权限,它只能向操作系统申请内存,此时java虚拟机会拥有一个初始内存,
此处额外说明一下eclipse.ini文件中的几个参数:
-vmargs -Xms256m -Xmx512m -XX:PermSize=256M -XX:MaxPermSize=512M
-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了
-Xms256m JVM初始分配的堆内存
-Xmx512m JVM最大允许分配的堆内存,按需分配
-XX:PermSize=256M JVM初始分配的非堆内存
-XX:MaxPermSize=512M JVM最大允许分配的非堆内存,按需分配
然后,java虚拟机在为程序开内存;当程序需要更多的空间时,假如把初始内存都占用了,怎么办?当然啦,它会继续向操作系统申请啊,如下图:
那么问题来啦,它不可能一直申请啊?对不对,总有用完的时候,当超过堆内存的最大值时候,就不会再分配了,会通知内存溢出!
二.谁在占用内存?
我相信这个图已经能够说明了,在jvm中有七块内存区域,现在我们只讨论其中的三块,栈块、堆块、方法区:
栈快中存储:对象的引用,基本数据类型;
堆块中存储:具体对象;
方法区中:完整的类结构。
三.举个实例进行分析:
person类
public class Person { public String name = null; public int age = -1; public Person() { // TODO Auto-generated constructor stub } public Person(String name, int age) { this.name = name; this.age = age; } public void showMe() { System.out.println(name + "/" + age); } }
main方法
public class PersonRun { public static void main(String[] args) { Person pj = null; pj = new Person("普京", 45); pj.showMe(); Person obm = null; obm = new Person("奥巴马", 50); obm.showMe(); int num = 10; System.out.println(num); int[] n = new int[]{1, 2, 3}; } }
内存分配图:
说明:
当我们编写一个person类时,当程序在运行时,类结构会被分配到方法区中,它只会有一份;
当我们Person pj = null;它被放在栈的区域,new Person("普京", 45);它放在了堆里,比如地址是1000d,它不会为方法再开空间,而是当我们用时会到方法中去找;
然后我们用一个引用去指向它,这样方便使用,比如pj在栈中的地址:100z,pj存储的是1000d地址,当我们调用showMe()方法时,先找到100z,在找到1000d,在找到方法区中的方法。
基本数据类型如 int num = 10;程序要使用它时,直接从栈中取;对于数组类型n,它存在引用跟pj类似。