Java内存分析个人理解

因为初学Java,学过的知识点容易忘记,所以最近在复习以前学过的东西,刚好复习到类和对象的概念,产生了疑问。

  • 疑问一:
Person p1 = new Person();

在第一遍学习的时候,一直以为p1就是对象,经过复习纠正错误

new Person()才是一个新的对象,在Java中都是先创建一个对象然后再来使用这个对象,这个p1是对new Person()这个对象的一个引用,相当于c语言里面的一个指针,可以说成是new Person()的地址,“=”不存在一个赋值的过程,只能算作一个传递地址的过程。

在这里简单的做一下内存分析:

分析java的内存dump文件 java内存占用分析_方法区

  • 疑问二
    按照这个理解,我写了如下代码:
package object_equal;
/*
 * 对于new的理解
 */
public class ObjectEqual {
	public static void main(String[] args) {
		Person p1 = new Person();
		Person p3 = new Person();
		p3 = p1;
		Person p2 = p1;
		p1.age = 10_0000;
		System.out.println(p1.age);
		p2.age = 11;
		System.out.println(p1.age);
		System.out.println(p3.age);
		p3.age = 167;
		System.out.println(p1.age);
		System.out.println(p2.age);
		p1.action();
		p2.action();
	}
}
class Person{
	int age;
	public void action() {
		System.out.println("我能唱跳rap篮球");
	}
}

运行结果如下:

分析java的内存dump文件 java内存占用分析_分析java的内存dump文件_02

解释如下:class Person中的变量和方法以及class ObjectEqual中的main方法都在方法区中,在程序运行的时候,首先main方法最先进入栈中开始执行。

创建第一个对象,p1进入栈中,并且在堆中开辟空间,从方法区中拿出变量,赋初值,也就是age = 0,同时将方法区中存放action方法的地址保存到堆中并且把新开辟的堆空间的地址赋给栈中的p1.

在创建一个对象,p3进入栈中,并且在堆中开辟空间,从方法区中拿出变量,赋初值age = 0,同时将方法区中存放action方法的地址保存到堆中(这里的地址值与创建第一个对象的地址值相同)并且把新开辟的堆空间的地址赋给栈中的p3.

这部我理解成一个赋地址值的操作,就是将p1指向的堆空间的地址赋给了p3,而p3原本指向的那块空间就变为垃圾空间在下次JVM回收之前如果还是没有被栈内存指向,就会被JVM回收。如下图所示:

分析java的内存dump文件 java内存占用分析_System_03

分析java的内存dump文件 java内存占用分析_方法区_04

接下来执行的Person p2 = p1;我认为只是一个地址赋值的过程将p1指向的堆空间的地址给了p2,但是因为p2没有new所以在堆中并没有开辟新的空间。

理解到这里,往下的运行过程就可以理解了

  • 疑问3
    常量在内存中的位置
    第一种,static的,作为类信息在类被加载时被存在静态的方法区,没毛病。
    第二种,非static的,作为对象属性,在对象创建的时候被初始化,存在堆里,没毛病。
    第三种,在方法里的。我们知道在方法被调用时会被加载到栈中进行执行,所以写在方法里的变量存在栈中。
  • 以上理解可能有不正确的地方,希望大佬纠正。