求救:静态变量(是个集合)的值是放在栈里的还是堆里的啊?

hz_haoyu 2009-09-27 03:44:31
定义一个hashtable的静态变量,value放置的是对象。
关于内存分配我的理解是:
该变量的定义是放在栈里的,包括对各对象的引用地址,然后真正的对象是放在堆中的,不知道对不对?
主要我的设计必要需要静态变量共享,然后该table封装的对象也是很多且都较大的,所以我就必须搞懂这个问题。
多谢大家帮助。
...全文
1675 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
戒子猪 2009-10-13
  • 打赏
  • 举报
回复
更新了BLOG,最近的一章:
http://blog.csdn.net/silentbalanceyh/archive/2009/10/13/4661230.aspx
主要分为Java内存模型的,你可以仔细看看
tfsict2008 2009-09-30
  • 打赏
  • 举报
回复
方法区,堆是整个虚拟机实例共享的。
栈,本地方法区时线程级别的。
bigbro001 2009-09-29
  • 打赏
  • 举报
回复
恍然大悟!

[Quote=引用 14 楼 zangxt 的回复:]
引用 13 楼 bigbro001 的回复:
不是说基本类型变量,引用都是存放在栈中的么?

这是别人胡扯的,不用相信。

放在什么位置跟你的定义有关。

比如
class Test{
  int i;//自然要随对象分配在堆里
    publi void test(){
      int j;//方法执行时才分配空间,在栈里
    }
}
[/Quote]
ZangXT 2009-09-29
  • 打赏
  • 举报
回复
提到jvm规范,记得上面说过,并不保证栈是连续的。
SuperZXT 2009-09-29
  • 打赏
  • 举报
回复
占楼。
ZangXT 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 zangxt 的回复:]
引用 19 楼 silentbalanceyh 的回复:
Java变量的存储和这个变量是否是静态变量、实例变量、块变量和局部变量没有直接的关系,关键在于该变量是一个原始变量还是一个对象的引用。针对Java的原始变量char/long/int/short/byte/float/double/boolean而言,它的存储模型就是针对内存栈的,它不存在把内容存储到内存堆的概念,只有对象的存储会牵涉到内存堆,例如:
int a = 0;
这样一句就是直接存储了该变量的值到内存栈的
A a = new A();
只有这样的格式才会存在将引用存到内存栈,将对象内从存储到内存堆里面。

至于Java里面的静态变量、实例变量、块变量和局部变量不是根据它的存储方式来划分的,主要在于它的生命周期,根据不同的生命周期进行变量的划分,静态变量是属于类的,所以只要类加载器一旦加载了它就有效了,具体内容你可以参考我BLOG上边Java的类和对象里面关于对象生命周期的章节,可能会有一个更加深入的了解:
http://blog.csdn.net/silentbalanceyh/archive/2009/09/24/4587371.aspx

看了你的blog,能写出那么多东西,而且有些是不错的。
但是看你很多基本概念都没弄明白,比如你根本分不清什么是引用,什么是对象,甚至认为this和super是两个“内置对象”。
好好看书吧
[/Quote]
sorry,说错了。
所谓分不清引用和对象是我看错了,没看明白“有这样的格式才会存在将引用存到内存栈,将对象内从存储到内存堆里面。”这句话的后半部分。
不礼貌,道歉。
hz_haoyu 2009-09-29
  • 打赏
  • 举报
回复
我听的越来越糊涂了。
ZangXT 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 silentbalanceyh 的回复:]
Java变量的存储和这个变量是否是静态变量、实例变量、块变量和局部变量没有直接的关系,关键在于该变量是一个原始变量还是一个对象的引用。针对Java的原始变量char/long/int/short/byte/float/double/boolean而言,它的存储模型就是针对内存栈的,它不存在把内容存储到内存堆的概念,只有对象的存储会牵涉到内存堆,例如:
int a = 0;
这样一句就是直接存储了该变量的值到内存栈的
A a = new A();
只有这样的格式才会存在将引用存到内存栈,将对象内从存储到内存堆里面。

至于Java里面的静态变量、实例变量、块变量和局部变量不是根据它的存储方式来划分的,主要在于它的生命周期,根据不同的生命周期进行变量的划分,静态变量是属于类的,所以只要类加载器一旦加载了它就有效了,具体内容你可以参考我BLOG上边Java的类和对象里面关于对象生命周期的章节,可能会有一个更加深入的了解:
http://blog.csdn.net/silentbalanceyh/archive/2009/09/24/4587371.aspx
[/Quote]
看了你的blog,能写出那么多东西,而且有些是不错的。
但是看你很多基本概念都没弄明白,比如你根本分不清什么是引用,什么是对象,甚至认为this和super是两个“内置对象”。
好好看书吧
ZangXT 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 bigbro001 的回复:]
Java codeclass Test{int i;//Test类对象在堆中,所以成员变量(全局变量)i在堆中,这个容易理解publicstatic List list=new ArrayList();//此处的成员变量在方法区,是因为static的原因么? publivoid test(){int j;//方法中的局部变量j在方法执行时才分配空间,所以在栈里 }
}
那么是否可以这样理解:
1.如果类的成员变量不是静态的,那么该成员变量(基本类型),或者该变量的引用,在对象生成时,随对象在堆中开辟一块空间存储
2.如果类的成员变量是静态的,那么在类加载时,在方法区中会开辟一块空间存储该静态变量(基本类型)或者该变量的引用,该引用所指向的对象在堆中
恳请ZangXT大侠指教?
[/Quote]
正确。
haojia0716 2009-09-29
  • 打赏
  • 举报
回复
static的东西是常驻内存的
hardycheng 2009-09-29
  • 打赏
  • 举报
回复
Java把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,
堆内存用来存放由new创建的对象和数组,在堆中分配的内存,由java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用new产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是java比较占内存的原因。
Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用
bigbro001 2009-09-29
  • 打赏
  • 举报
回复
最后试着总结总结ZangXT大侠的话:

变量在内存中位置的3种情况:

1.类的非静态成员变量
类的对象产生时,堆内存中开辟一块空间存放该对象,以及该对象的成员变量,如果该成员变量是个引用,那么这个引用所指向的实际对象也在堆内存中

2.类的静态成员变量
JVM加载该类时,方法区开辟一块空间存放该变量,如果该成员变量是个引用,那么这个引用所指向的实际对象在堆内存中

3.方法中的局部变量
线程执行到该变量声明语句时,栈内存中开辟一块空间存放该变量,如果该局部变量是个引用,那么这个引用所指向的实际对象在堆内存中
戒子猪 2009-09-29
  • 打赏
  • 举报
回复
内存栈和内存堆最大的区别是它们一个是连续的内存块,一个是非连续的内存块,非连续的内存块在C++使用链表的时候我们可以明显感觉到,实际上真正在存储的时候分配内存空间,会出现“堆中有栈”的情况,这种情况相对复杂,JVM提供了一定的算法进行它们相互之间的通信,就如同用栈中的引用去引用堆中的对象一样,具体情况可以参考以下JVM的规范里面有很严格的说明。找个时间我重新整理一个Java内存模型的章节把它们底层的原理全部解析出来。我不保证我的回复是正确的,但是可以做个参考。所以针对复杂的Java对象而言,不是所有的内容全部打包存储到内存堆上的,如果是按照这种格式来存储,JVM在调用的时候可能更加复杂,它还是遵循了一定的Java存储规范进行操作的。对于一个复杂的对象而言,对象本身是存储在内存堆上的,但是针对对象里面的内容,是否包含引用、是否包含了原始变量、是否存在内存堆、是否存在了内存栈这些都是有一定的结构的。所以不能单纯地认为Java对象里面所有的内容全部打包存储在内存堆里面,这种说法是不严谨的。
戒子猪 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zangxt 的回复:]
引用 13 楼 bigbro001 的回复:
不是说基本类型变量,引用都是存放在栈中的么?

这是别人胡扯的,不用相信。

放在什么位置跟你的定义有关。

比如
class Test{
  int i;//自然要随对象分配在堆里
    publi void test(){
      int j;//方法执行时才分配空间,在栈里
    }
}
[/Quote]
这种说法有点问题,虽然i是Test对象里面的内容,但是存储的时候还是存在内存栈上的,因为它不是对象创建的时候进行内存的管理,二是在Test对象进行初始化的时候进行的内存分配,主要还是牵涉到一个对象生命周期的管理问题。对象里面的属性也是严格按照JVM的存储模型来进行操作的,上边代码里面i是属于对象Test的,但是存储的时候和对象不是一样的存法
戒子猪 2009-09-29
  • 打赏
  • 举报
回复
Java变量的存储和这个变量是否是静态变量、实例变量、块变量和局部变量没有直接的关系,关键在于该变量是一个原始变量还是一个对象的引用。针对Java的原始变量char/long/int/short/byte/float/double/boolean而言,它的存储模型就是针对内存栈的,它不存在把内容存储到内存堆的概念,只有对象的存储会牵涉到内存堆,例如:
int a = 0;
这样一句就是直接存储了该变量的值到内存栈的
A a = new A();
只有这样的格式才会存在将引用存到内存栈,将对象内从存储到内存堆里面。

至于Java里面的静态变量、实例变量、块变量和局部变量不是根据它的存储方式来划分的,主要在于它的生命周期,根据不同的生命周期进行变量的划分,静态变量是属于类的,所以只要类加载器一旦加载了它就有效了,具体内容你可以参考我BLOG上边Java的类和对象里面关于对象生命周期的章节,可能会有一个更加深入的了解:
http://blog.csdn.net/silentbalanceyh/archive/2009/09/24/4587371.aspx
hz_haoyu 2009-09-29
  • 打赏
  • 举报
回复
谢谢 ZangXT
让我理解了一些。
ZangXT 2009-09-29
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 hz_haoyu 的回复:]
Object o = new Object();  //线程执行到这里的时候,o的变量在哪里,new Object()在哪里?
static Object o = new Object();  //线程执行到这里的时候,o的变量在哪里,new Object()在哪里?

各在内存在栈、堆、方法区?
多谢。
[/Quote]
关键:先区分引用和对象的实际关系。
每个线程有一个自己的栈。

Object o = new Object(); //线程执行到这里的时候,o的变量在哪里,new Object()在哪里?
如果该声明是在方法中的话,o是个局部引用变量(或者说就是指针,地址),存在于线程的栈里。实际对象在堆中。

如果该声明是在类定义中的话,
比如
class Test{
Object o = new Object();
}
o是个nonstatic field,引用o作为Test对象的一部分存在于堆中,而o指向的new Object 也在堆中,但不是上面提到的o所在Test对象的一部分。

static Object o = new Object();
o在方法区,实际对象在堆中。
AldisZhan 2009-09-29
  • 打赏
  • 举报
回复
堆(Heap)
运行时数据区域,所有类实例和数组的内存均从此处分配。Java 虚拟机启动时创建。对象的堆内存由称为垃圾回收器 的自动内存管理系统回收。
组成
News Generation (Young Generation即图中的Eden + From Space + To Space)
Eden 存放新生的对象
Survivor Space 两个 存放每次垃圾回收后存活的对象
Old Generation (Tenured Generation 即图中的Old Space) 主要存放应用程序中生命周期长的存活对象

非堆内存
JVM具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构,如运行时常数池、字段和方法数据,以及方法和构造方法的代码。它是在 Java 虚拟机启动时创建的。
除了方法区外,Java 虚拟机实现可能需要用于内部处理或优化的内存,这种内存也是非堆内存。 例如,JIT 编译器需要内存来存储从 Java 虚拟机代码转换而来的本机代码,从而获得高性能。
组成
Permanent Generation (图中的Permanent Space) 存放JVM自己的反射对象,比如类对象和方法对象
native heap

希望有所帮助
hz_haoyu 2009-09-29
  • 打赏
  • 举报
回复
Object o = new Object(); //线程执行到这里的时候,o的变量在哪里,new Object()在哪里?
static Object o = new Object(); //线程执行到这里的时候,o的变量在哪里,new Object()在哪里?

各在内存在栈、堆、方法区?
多谢。
ZangXT 2009-09-29
  • 打赏
  • 举报
回复
附上一个sun hotspot中的对象内存布局图
加载更多回复(17)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧