关于Java成员变量、局部变量、方法,在JVM的内存空间分配

x33g5p2x  于2022-02-18 转载在 Java  
字(2.6k)|赞(0)|评价(0)|浏览(398)

1、变量类型


2、类的结构
下面是一般类的结构

//类体=属性+状态(即:类体=变量+方法)
public class 类名{	//类名最好首字母大写的英文
	String name;	//在方法体外,所以是成员变量
	//下面是一个main方法(程序入口的主方法)
	public static void main(String[] args){
		int i;		//在main方法体内,所以是局部变量
	}		
}

3、类的编译运行时JVM内存的变化

JVM(Java 虚拟机)主要包括三个内存空间。分别是:栈内存、堆内存、方法区内存。(堆内存和方法区内存各一个。一个线程一个栈内存)

首先类编译后产生.class的字节码文件,执行类加载器把.class的字节码文件加载到方法区内存(方法的代码片段以及整个类的代码片段都是存储到方法区内存当中)
找到类的程序入口(即主方法)执行到什么语句就会在对应的内存分配空间。

例如程序执行过程中使用new运算符创建的Java对象,存储在堆内存当中。对象内部有实例变量,所以实例变量也存储在堆内存当中。

方法调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈。方法执行结束后,该方法所属的内存空间释放,称为弹栈。
下面分析一下案例:

public class Computer{
	double price;	//价格
	String type;	//型号
}

public class Student{
	int number;		//学号
	String name;	//姓名
	Computer com;	
}

public class Test{
	public static void main(String[] args){
	
/*  “=”符号右边先执行 new Computer()严格来说是在堆内存里面开辟了一个新的Computer对象空间。
对象的空间地址给了一个名字叫computer的引用而已,引用类型就是第一个Computer。*/
		Computer computer=new Computer();	
/*  “=”符号右边先执行 new Student()严格来说是在堆内存里面开辟了一个新的Student对象空间。
对象的空间地址给了一个名字叫student的引用而已,引用类型就是第一个Student。*/
		Student student=new Student();
		//student.com的引用指向了computer的引用地址(相当于将computer的引用地址给student.com的引用)
		student.com=computer;
		computer.price=4999.9;
		System.out.println(student.com.price);  //4999.9
		System.out.println(student.com.type);	//null,因为没有赋值,String默认值是null
		
		System.out.println(computer.price);     //4999.9
		System.out.println(computer.type);		//null,因为没有赋值,String默认值是null
		
		student.name="jack";
		
		m();
		System.out.println(student.number);		//0,因为没有赋值,int默认值是0
		System.out.println(student.name);		//jack
	}
	public static void m(){
		String str="handsome";
		System.out.println("I am really "+str);
	}
	
}
下面是运行结果:
---------------------------------
4999.9
null
4999.9
null
I am really handsome
0
jack

以上有三个类分别是Computer类、Student类、Test类、编译运行将产生Computer.class、Student.class、Test.class的字节码文件。因为还用到String类,所以String.class等字节码文件一起载入到方法区,然后找到程序入口main,方法main被压栈。

Computer computer=new Computer(); 在堆里创建Computer 对象,实例变量有price和type,然后对象的地址0x1234给到引用computer。引用computer在main方法里面,所以引用computer在栈。Student student=new Student(); 也跟上面一样。

student.com=computer; 是将computer的地址0x1234给到Student对象的com实例变量里。所以student.com.price是student指向的0x2451地址找到com,com指向的0x1234地址找到price;computer.price是computer指向的0x1234地址找到price;虽然结果是相同的,但是student.com.price可以体现关联性

computer.price=4999.9; 与 student.name=“jack”;都是将地址给到对应的引用上。接下来然后遇到m();的调用,把它压栈,方法里面的局部变量也在栈里面,方法m();执行完弹栈,跟随的局部变量str也失效。然后执行完代码mian方法也弹栈。(先进后出,后进先出)

扩展
  • 访问实例变量的语法格式:
    读取数据——>引用.变量名;修改数据——>引用.变量名=值;
  • 数据类型:
    数据类型分为基本数据类型(byte short int long float double boolean char)和引用数据类型(开发包的类(String…等)以及自己定义的类)
    数据类型的默认值

  • 三块内存当中变化最频繁的是栈内存,最先有数据的是方法区内存,垃圾回收器主要针对的是堆内存。
  • 垃圾回收器(自动垃圾回收机制、GC机制)什么时候会考虑将某个Java对象的内存回收呢?
问:什么时候堆内存中的Java对象会变成垃圾呢?
 			答:没有更多的引用指向它的时候
 			答:这个对象无法被访问,因为访问对象只能提通过引用的方式访问
  • 空引用访问“实例“相关的数据一定会出现空指针异常。

以上是个人对JVM的理解,若有错误欢迎指出

相关文章