码迷,mamicode.com
首页 > 其他好文 > 详细

深入理解JVM_内存管理对象访问与大小02

时间:2017-06-24 18:30:23      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:dwz   isp   ccs   bs4   suv   pig   pcr   dem   创建   

1、对象访问:
     在java语言中,对象访问如何进行的?
     (1)最简单的访问,也会涉及java栈、java堆和方法区这三个最重要的内存区域之间的关联关系。
          Object obj = new Object();
          <1> “Object obj”:反应到java栈的本地变量表中,作为一个reference类型数据出现。
          <2> “new Object()”:反应到java堆中,形成一块存储了Object类型所有实例数据值的结构化内存。这块内存的长度不是固定的。
          <3> java堆中还必须包含能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些类型数据则存储在方法区中。
     (2)由于reference类型在java虚拟机规范里只规定了一个指向对象的引用,并没有定义这个引用应该通过哪种方式去定位,以及访问到java堆中的对象的具体位置。主流的访问方式有两种:
          <1> 使用句柄;
               Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,此句柄中包含了:“对象实例数据”和“类型数据”各自具体的地址信息。具体如下图:
技术分享
          
          <2> 直接指针。
               Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象地址。如下图:
技术分享
          <3> 两种方式的优缺点:
               (1) 句柄优点:reference中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而reference本身不需要被改变。
               (2) 直接指针优点:速度很快,它节省一次指针定位的时间开销。Sun HotSpot而言,就是使用此种方式。
          
2、Java对象的大小:
     基本数据的类型的大小是固定的。非基本类型的java对象,其大小就值得商榷了。
     在java中,一个空object对象的大小是8byte。这个大小只是保存堆中一个没有任何属性的对象的大小。如下语句:
     Object obj = new Object();
     这样在程序中完成了一个java对象的生命,但是它所占的空间为:4byte+8byte。期中4byte就是上面所说的java栈中保存引用的所需要的空间,而8byte则是java堆中对象的信息。因为java中非基本类型的对象都需要继承Object对象,所有不论什么样的java对象,其大小都必须大于8byte。
     有了Object对象的大小,我们就可以计算其他对象的大小了。
     Class NewObject {
          int count;
          boolean flag;
          Object ob;
          }
     其大小为:空对象大小(8byte)+int大小(4byte)+Boolean大小(1byte)+空Object引用的大小
(4byte)=17byte。但是因为Java在对对象内存分配时都是以8的整数倍来分,因此大于17byte的最接
近8的整数倍的是24,因此此对象的大小为24byte。
 
     程序计数器、虚拟机栈、本地方栈3个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出而执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的。
 
 
以下内容待定:
2、内存分配
     java对象所占用的内存主要从堆上进行分配,堆是所有线程共享的,因此堆上分配内存时需要进行加锁,导致了创建对象开销比较大。当堆上空间不足时,会触发GC,如果GC后空间仍然不足,则出OutOfMemory错误信息。
     JDK提升内存分配的效率,会为每个新创建的线程在新生代的Eden Space上分配一块独立的空间。这个空间称为TLAB(Thread Local Allocation Buffer),其大小有JVM根据运行情况计算而得。
     可通过:-XX:TLABwasteTargetPercent来设置TLAB可占用的Eden Space的百分比,默认值为1%。
     JVM将根据这个比率,线程数量及线程是否频繁分配对象来给每个线程分配合适大小的TLAB空间。在TLAB上分配内存时不需要加锁,因此JVM在给线程中的对象分配内存时会尽量在TLAB上分配,如果对象过大或TLAB空间已用完,则仍然在堆上进行分配。
     因此在编写java程序时,通常多个小的对象比大的对象分配起来更加高效。可通过在启动参数上增加-XX:+PrintTLAB来查看TLAB空间的使用情况。
     除了从堆上分配及从TLAB上分配外,还有一种基于逃逸分析直接在栈上进行分配的方式。

深入理解JVM_内存管理对象访问与大小02

标签:dwz   isp   ccs   bs4   suv   pig   pcr   dem   创建   

原文地址:http://www.cnblogs.com/yymmx888/p/7073756.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!