A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© zuochbd 中级黑马   /  2014-9-25 14:52  /  4063 人查看  /  17 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

5黑马币
本帖最后由 caixingke 于 2014-9-25 14:57 编辑

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

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

最佳答案

查看完整内容

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

17 个回复

倒序浏览


必须创建所有的对象

创建完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-26 19:06
回复 使用道具 举报
http://sunqi.iteye.com/blog/1917802
回复 使用道具 举报
对象占用字节数=基本的8字节+基本数据类型所占的+对象引用所占的

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

点评

我想知道的是一个对象空间所存放的所有可能的信息.,  发表于 2014-9-27 23:12
回复 使用道具 举报
alpha.huai 发表于 2014-9-27 21:48
有本书叫[深入理解Java虚拟机:JVM高级特性与最佳实践].周志明,你可以搜索一下。
java虚拟机在运行的时候 ...

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

比如:

对象自己存放自己的引用干嘛,如果他存放了自己的引用,垃圾收集器还能收集他吗
回复 使用道具 举报

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

不过long占用64字节  目测板凳回答有点小问题  
新手 如果说错了 请轻喷 谢谢
回复 使用道具 举报
这个问题我也想问
回复 使用道具 举报
确实,在c中可以通过sizeof获得对象的内存大小,而java对象存储的东西相对于c来说要多多,通过对象恩能够做的事情也很多,比如反射等
回复 使用道具 举报
我们用new操作符生产一个对象的时候,我是来学习的 ????看毕老师视频的时候觉得懂了,离了视频就似懂非懂了.....…………^..^
回复 使用道具 举报
自身的构造方法以及object的super()方法
回复 使用道具 举报
李票 中级黑马 2014-12-27 15:46:34
15#
还存放有java垃圾回收器(Java编写的),没有办法得到的,因为这根据对象的规模大小不确定
回复 使用道具 举报
毕老师视频上有的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马