黑马程序员技术交流社区

标题: java对象空间存储了哪些内容? [打印本页]

作者: zuochbd    时间: 2014-9-25 14:52
标题: java对象空间存储了哪些内容?
本帖最后由 caixingke 于 2014-9-25 14:57 编辑

C/C++的结构体和类对象的空间中, 所存的东西很明确(教科书通常都会讲其存放的规则), 而且我们可以通过sizeof来获得其对象的存储空间的大小.
但是Java呢, 在对象的空间中, 除了存放我们所知道的数据成员外, 还存哪些东西呢?

另外, 我们是不是没办法得知这个对象所占据的存储空间大小?


作者: flypig    时间: 2014-9-25 14:52


必须创建所有的对象

创建完reference之后,你就得往上面连新的对象。大体上,用new关键字来作这件事,关键词new的意思是,“给我创建一个新的那种类型的对象。”所以在上述例程中,你可以用:String s=new String("asdf"); 它不公表示“给我创建一个新的String“,而且还用字符串参数告诉它“如何”制作这个String。当然,String并不是唯一的类,JAVA编程基本上就是在创建类。

数据存在哪里?

对程序运行时各部份是如何展开的——特别是内存是如何分配的,作一直观的描述还是很有必要的。数据可以存储在以下六个地方:

1、寄存器(Registers):这是反映最快的存储,因为它所处位置不同,在处理器里。不过寄存器的数量非常有限,所以它是由编译器分配的。你非但不能直接控制寄存器,甚至连它存在的证据也找不到。

2、栈(Stack):位于“常规内存区(General Random-access Memory area)”里,处理器可以通过栈指针(Stack pointer)对它进行直接访问。栈指针向下移就创建了新的存储空间,向上移就释放内存空间。这是仅次于寄存器的最快,最有效率的分配内存的方法。由于JAVA编译器必须生成能控制栈指针上移和下移的代码,所以程序编译的时候,那些将被存储在栈中的数据的大小和生命周期必须是已知的。这使得程序的灵活性受到了限制,所以尽管JAVA把某些数据——特别是对象的Reference存放在栈里,但是对象本身并没有放在栈里。

3、堆(Heap):这是一段“多用途的内存池”(General-purpose pool of memory,也在内存里面),所有JAVA对象都保存在这里。同栈不同,堆的优点是,分配空间的时候,编译器无需知道分配多少空间,或者这些数据会在堆里呆多长时间。因此使用堆的空间会比较灵活。只要你想创建对象,用new就行了,程序执行的时候自会在堆里分配空间。当然你得为这种灵活性付出代价,分配堆的存储空间要比分配栈的慢一些(假如你能像C++那样在栈里创建对象的话)

4、静态存储(Static storage):“静态”在这里的意思就是“在固定的位置”(尽管它还是在RAM里面),静态存储里面的数据在整个程序的运行期间都能访问到。你可以用Static关键词来指明对象中的某个元素是表态的,但是JAVA对象本身是决不会放到静态存储中去的。

5、固定存储(Constant storage):常量值通常直接放在程序里,这样它们就不会被改动了,因而也更安全。有时常量还能为自己设置界限,这样在嵌入式系统中,你就能选择是不是把它们放到ROM里面去。

6、非内存的存储(Non-Ram Strorage):如果数据完全独立于程序,那么即使程序不运行,它也应该还在;即使程序失去了对数据的控制,它也仍然还在。两个最主要的例子是“流对象(Streamed Object)”和“Persistent对象(Persistent Object)”,大致上说,前者是一种会被送往另一台机器的,由对象转化而成的字节流;这类存储的奥妙就在于对象被转化成了某种能保存在其它介质上的东西,但是要用的时候,又能在内里重建;JAVA提供了“轻量级Persistence(Lightweight Persistence)”的支持;未来JAVA可能会提供更为完整的Persistence的支持。

作者: 余丽丽    时间: 2014-9-25 19:10
http://sunqi.iteye.com/blog/1917802
作者: 小叶子    时间: 2014-9-27 16:45
对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的

比如:
class B{
    Integer a;
    long b;
    byte c;
}
占 8(基本)+16(long8+byte1=9,对齐到16)+8(对象引用4,对齐到8)=32个字节
作者: alpha.huai    时间: 2014-9-27 21:48
有本书叫[深入理解Java虚拟机:JVM高级特性与最佳实践].周志明,你可以搜索一下。
java虚拟机在运行的时候会把内存分为几个部分,通过垃圾回收算法把失去引用的对象销毁。
ong beforeMemory=Runtime.getRuntime().totalMemory();
MyObject obj=new MyOjbect();
long afterMemory=Runtime.getRuntime().totalMemory();
System.out.println("Memory used:"+(beforeMemory-afterMemory));
这样可不可以知道你想要的结果。
作者: alpha.huai    时间: 2014-9-28 00:28
alpha.huai 发表于 2014-9-27 21:48
有本书叫[深入理解Java虚拟机:JVM高级特性与最佳实践].周志明,你可以搜索一下。
java虚拟机在运行的时候 ...

我才发现两个帖子都是你发的T_T
作者: ooEye    时间: 2014-9-28 23:47
来学习了,我看过视频,但是忘了
作者: 易孟飞    时间: 2014-10-3 04:04
JAVA的对象也是仅仅存储数据成员,函数成员会被统一另外的表中
作者: 易孟飞    时间: 2014-10-3 04:06
本帖最后由 易孟飞 于 2014-10-3 04:07 编辑
小叶子 发表于 2014-9-27 16:45
对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的

比如:

对象自己存放自己的引用干嘛,如果他存放了自己的引用,垃圾收集器还能收集他吗
作者: 紫缘ぶ逸影    时间: 2014-10-10 10:35

板凳说的对啊  就是:对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的

不过long占用64字节  目测板凳回答有点小问题  
新手 如果说错了 请轻喷 谢谢
作者: 斗神_    时间: 2014-10-15 14:39
这个问题我也想问
作者: axing110    时间: 2014-10-19 19:33
确实,在c中可以通过sizeof获得对象的内存大小,而java对象存储的东西相对于c来说要多多,通过对象恩能够做的事情也很多,比如反射等
作者: 大鱼吃小鱼    时间: 2014-11-19 22:49
我们用new操作符生产一个对象的时候,我是来学习的 ????看毕老师视频的时候觉得懂了,离了视频就似懂非懂了.....…………^..^
作者: 1103--英伦风格    时间: 2014-11-22 21:33
自身的构造方法以及object的super()方法
作者: 李票    时间: 2014-12-27 15:46
还存放有java垃圾回收器(Java编写的),没有办法得到的,因为这根据对象的规模大小不确定
作者: 李大大    时间: 2015-3-23 22:48
毕老师视频上有的




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2