Java内存管理

Java内存区域分为:

  • 方法区(Method Area):所有线程共有
  • 虚拟机栈(VM Stack):每一个线程独有
  • 本地方法栈(Native Method Stack):HotSpot虚拟机直接将本地方法栈和虚拟机栈合二为一。
  • 堆(heap):所有线程共有
  • 程序计数器(Program Counter Register):每个线程独有,只记录非native方法
/**
 * 运行时, jvm 把AppMain的信息都放入方法区
 */
public class AppMain {
    /**
     * main 方法放入栈区。
     */
    public static void main(String[] args) {
        Sample test1 ;
        System.out.println("Sample test1 statement");
        test1= new Sample(" 测试1 ");   //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面   
        Sample test2 = new Sample(" 测试2 ");

        test1.printName();
        test2.printName();
    }
}

/**
 * 运行时, jvm 把Sample的信息都放入方法区
 */
class Sample {
  
    static{
           System.out.println("Sample class loaded");
    }
   //new Sample实例后, name 引用放入堆里,  name 对象放入堆里
    private String name;      

    public Sample(String name) {
        this.name = name;
    }

    /**
     * print方法本身放入 方法区里。
     */
    public void printName() {
        System.out.println(name);
    }
}

程序运行过程:
Jvm首先加载AppMain类进方法区,然后执行main()方法。test1是局部变量会加载到栈中,然后实例化Sample对象,此时需要加载Sample类到方法区,然后在堆中new出一个Sample的对象,地址交给test1在栈中保存。**然后调用printName()方法,Jvm将继续执行后续指令,在堆区里继续创建另一个Sample实例,然后依次执行它们的printName()方法。当JAVA虚拟机执行test1.printName()方法时,JAVA虚拟机根据局部变量test1持有的引用,定位到堆区中的Sample实例,再根据Sample实例持有的引用,定位到方法去中Sample类的类型信息,从而获得printName()方法的字节码,接着执行printName()方法包含的指令.
(printName()会进去栈中吗?在栈中怎么存放?Sample的name属性是放在堆中还是栈中?)
方法进入栈,形成一个栈帧,name属性放在堆中,只有方法中的变量进入栈中。

疑问:到底是test1变量在声明时加载Sample还是在new的时候加载Sample到方法区?
经过打印log发现Sample是在new的时候加载,在声明的时候并不加载。
深入理解JVM(1) : Java内存区域划分
Java里的堆(heap)栈(stack)和方法区(method)

http://www.cnblogs.com/gw811/archive/2012/10/18/2730117.html
http://www.cnblogs.com/vamei/archive/2013/04/28/3048353.html

你可能感兴趣的:(Java内存管理)