目录
内存结构
程序计数器
-
作用,是记住下一条jvm指令的执行地址
-
是线程私有的
-
在线程上下文切换的过程中需要记录到下一条要执行的指令的地址,等到线程再次被调度到执行的时候,还是根据该线程的程序计数器,来找到下一条要执行的指令的地址
-
每个线程都有自己独有的程序计数器
-
唯一一个内存不会溢出的
-
随着线程创建而创建,随着线程销毁而销毁
栈
栈可以说是虚拟机栈中的局部变量表
局部变量表中存放了编译期可知的各种基本数据类型,对象引用(不等于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。
-
线程运行需要的内存空间
-
栈帧(参数,局部变量,返回地址):每个方法运行时需要的内存
-
一个栈由多个栈帧组成
-
栈先入后出
栈的演示
主方法调用method1,method1调用method2
method2栈帧在栈的顶部
method1在栈的中间
主方法在栈的底部
局部变量,参数在method2栈帧内占用内存
方法结束完后一步步从顶至下弹出,占用的内存也会被释放掉
问题辨析
-
垃圾回收是否涉及栈内存:不需要,栈内存是一次次方法调用产生的栈帧内存,而每一次方法调用后都会被弹出栈,自动被回收掉,不需要垃圾回收来涉及栈内存
-
栈内存分配越大越好吗:栈内存过大会导致线程数变少,物理内存大小是有限的,假设物理内存为500M,如果栈内存为250M,能运行的线程就只有俩个
-
方法内的局部变量是否线程安全:局部变量是线程私有的,不会受到其他线程干扰,是线程安全的。但是给局部变量加上static修饰,就会有线程安全问题了!如果方法内局部变量没有逃离方法的作用范围,它就是线程安全的。如果局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全。