浅谈JVM与内存分配

2017-05-06 02:40

一.程序内存分配

初始内存分配

当一个程序准备运行时,它首先向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与内存分配0

 

那么问题来啦,它不可能一直申请啊?对不对,总有用完的时候,当超过堆内存的最大值时候,就不会再分配了,会通知内存溢出!

二.谁在占用内存?

浅谈JVM与内存分配1

我相信这个图已经能够说明了,在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};
    }

}

内存分配图:

浅谈JVM与内存分配2

说明:

当我们编写一个person类时,当程序在运行时,类结构会被分配到方法区中,它只会有一份;

当我们Person pj = null;它被放在栈的区域,new Person("普京", 45);它放在了堆里,比如地址是1000d,它不会为方法再开空间,而是当我们用时会到方法中去找;

然后我们用一个引用去指向它,这样方便使用,比如pj在栈中的地址:100z,pj存储的是1000d地址,当我们调用showMe()方法时,先找到100z,在找到1000d,在找到方法区中的方法。

基本数据类型如  int num = 10;程序要使用它时,直接从栈中取;对于数组类型n,它存在引用跟pj类似。