JVM内存结构
程序计数器Program Counter Register,也叫寄存器
- 作用:记住下一条jvm指令的执行地址
- 特点
- 是线程私有的
- 不在存在内存溢出
虚拟机栈Java Virtual Machine Stacks
- 是每个线程运行所需要的内存空间
- 每个栈由多个栈桢(Frame,即调用的每个方法)组成,对应着每次方法调用时所占用的内存,保存着方法的参数、局部变量,返回值
- 每个线程只能有一个活动栈桢,对应着当前正在执行的那个方法
问题辨析
- 垃圾回收涉及栈内存吗?
不涉及,因为栈桢在执行完成后就出栈了,不需要手动回收 - 栈内存分配越大越好吗?
不是,一个栈对应一个线程运行所需要的空间,物理内存大小是固定的,所以栈内存越小,可运行线程数越多;栈内存越大,可运行线程数越少。所以栈内存不是分配的越大越好。 - 方法内的局部变量是否线程安全?
- 如果方法内的局部变量没有逃离方法的作用范围,那么它是线程安全的
//s1的声明方式是线程安全的
public static void method1(){
//StringBuffer:线程不安全的
StringBuffer s1 = new StringBuffer();
s1.append("A");
s1.append("B");
...
}
- 如果局部变量引用了对象,并逃离了方法的作用范围,那么需要考虑线程安全
//先说结论,这个是线程不安全的
//StringBuilder是线程不安全的
public static void method2(StringBuiler sBuilder){
sBuilder.append("A");
sBuilder.append("B");
...
}
//我们在main操作一下
public static void main(String[] args){
StringBuilder s = new StringBuilder();
new Thread(()->{
s.append("a");
s.append("b");
}).start();
method2(s);
}
它们会抢s的资源,是线程不安全的。严格的来说sBuilder不是方法内的局部变量,它是形参的局部变量,形参也会存在局部变量表中
//结论:不是线程安全的(有可能存在问题)
public static StringBuilder method3(){
StringBuilder s1 = new StringBuilder();
s1.append("A");
s1.append("B");
...
return s1;
}
这次不传参数,而是返回。引用类型一返回出去可能被其他位置上的多个线程所调用
栈内存溢出的情况
1 栈桢过多,比如递归调用且程序没有出口
2 栈桢过大,即一个栈桢就充满了整个栈,一般这种情况见不到,因为一个栈桢中就存储一个方法中的相关参数,用不了那么大的内存
未完待续...
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤