精华内容
下载资源
问答
  • CSS段落对齐方式
    2021-08-04 09:27:24

    CSS段落对齐有两种方式:水平对齐和垂直对齐。

    1.水平对齐:

    (1)、text-align:left;         //左对齐

    (2)、text-align:right;      //右对齐

    (3)、text-align:center;   //居中对齐

    (4)、text-align:justify;  //两端对齐

    2.垂直对齐:

    (1)、vertical-align:top;  //顶部对齐

    (2)、vertical-align:bottom; //底部对齐

    (3)、vertical-align:middle;  //中间对齐

    【CSS】定义元素的对齐方式

    1.文本内容居中对齐:text-align.扩展用法:父元素嵌套子元素时,且子元素的宽度小于父元素宽度,使用text-align:center,可以实现子元素的居中对齐. ..

    测开之路九十三:css之文字样式和段落对齐

    引用css 字体族 字体类型和尺寸 em:字体按倍数缩放 font-weight:调整文字的粗细 段落对齐:text-align 左对齐:left 右对齐:right 居中对齐:center 两边对齐 ...

    css text-align-last设置末尾文本对齐方式

    text-align-last:auto | start | end | left | right | center | justify auto: 无特殊对齐方式. left: 内容左对齐. cen ...

    css属性之统一设置文本及div之间的对齐方式

    设为 Flex 布局以后,子元素的float.clear和vertical-align属性将失效.hdp-uf{ display: -webkit-box; /* 老版本语法: Safari, iOS ...

    精通CSS+DIV网页样式与布局--CSS段落效果

    在上一篇博文中,小编主要详细的介绍了CSS是如何控制文字的显示效果,随着需求的不断变更,那么我们如何对段落进行相关操作,以达到我们想要的效果呢,接下来,为了需要,小编继续来完善CSS对段落的控制的显示 ...

    python 全栈开发,Day46(列表标签,表格标签,表单标签,css的引入方式,css选择器)

    一.列表标签 列表标签分为三种. 1.无序列表

    • ,无序列表中的每一项是
    • 英文单词解释如下: ul:unordered list,“无序列表”的意思. li:lis ...

      CSS文本对齐text-align详解

      1.语法 text-align具体参数如下: 语法:text-align : left | right | center | justify 说明:设定元素内文本的水平对齐方式. 参数:left :  ...

      CSS——段落处理

      ...

      Day46(列表标签,表格标签,表单标签,css的引入方式,css选择器)

      一.列表标签 列表标签分为三种. 1.无序列表

      • ,无序列表中的每一项是
      • 英文单词解释如下: ul:unordered list,“无序列表”的意思. li:lis ...

        随机推荐

        CSS网页制作常用标签

        做了一个简单的网页,从布局到加内容,遇到了很多小问题.很多标签和属性都不会用或者忘记了.所以以此记录一下. 一.如何将边框四角变圆?(或做一个圆形) 顾名思义,如果要更改边框的角需要用到边框(bord ...

        使用block进行界面之间的反向传值

        目标:在两个独立的控制器的界面之间进行反向传值 关键技术:block 代码编写及运行环境:Xcode6.4 / 模拟器8.4 语言:Objective-C 注:使用纯代码实现,不使用xib/story ...

        Java集合类学习笔记(Map集合)

        Map用于保存具有映射关系的数据,因此Map集合里保存着两组数据,一组用于保存Map的key,一组用于保存key所对应的value. Map的key不允许重复. HashMap和Hashtable都是 ...

        基于Metronic的Bootstrap开发框架经验总结(9)--实现Web页面内容的打印预览和保存操作

        在前面介绍了很多篇相关的的系列文章,这些内容基本上覆盖到了我这个Bootstrap框架的各个主要方面的内容,总体来说基本达到了一个稳定的状态,随着时间的推移可 ...

        75.Android之基本架构

        转载:http://www.cnblogs.com/lijunamneg/archive/2013/01/18/2866953.html Android其本质就是在标准的Linux系统上增加了Java ...

        Oracle VM VirtualBox 虚拟机与主机共享文件

        安装增强功能(参考文档) VirtualBox自带了一个增强工具Sun VirtualBox Guest Additions,这是实现虚拟机与真实主机共享的关键.启动虚拟机后,点击控制菜单“设备”→“ ...

        Python中的图形库

        Python中的图形库 根据Python 2.x的官网文档的解释: Graphical User Interfaces with Tk 和 Other Graphical User Interface ...

        ZOJ 3728 Collision

        ---恢复内容开始--- 今天无事水一水,结果就看到这个水题了! 题意思是 有俩个区域如图 求在俩个圆之间的运动时间 给出 初始的开始点和速度的矢量式;而且这个点 不再俩个圆之间的区域,且碰到内测园会 ...

        5.关于QT中的网络编程,QTcpSocket,QUdpSocket

         1 新建一个项目:TCPServer.pro A  修改TCPServer.pro,注意:如果是想使用网络库,需要加上network SOURCES += \ TcpServer.cpp \ T ...

        Object.assign简单总结

        定义 Object.assign方法用来将源对象source的所有可枚举属性复制到目标对象target.至少需要两个对象作为参数,第一个参数为源对象,后面的均为目标对象.(以下用source代指源对象 ...

    更多相关内容
  • AutoCad对象对齐,均布对象工具,包括左对齐、居中对齐,右对其,上对其、下对齐等6种对其方式,此外还有指定点对其,指定对象对齐,均布工具有垂直均布、水平均布等8种均布方式,还包括指定间距均布,制定范围均布...
  • 选中多个对象,再用工具栏中的对齐对象工具 和分布对象工具 来调整对象对齐方式和分布方式。  例如,选中3个对象,单击对齐对象工具,选择“左边缘”使3个对象的左边缘对齐,如图1 所示;单击分布对象工具,...
  • FIXUILABELS 遍历包含在当前 MATLAB 图窗中的 java 对象,并为所有“文本”样式的 uicontrol 调整底层 java 对象,以便它们的文本更好地与相邻的“编辑”样式 uicontrol 在同一高度对齐。 FIXUILABELS(FIG) 修复图...
  • 下面小编就为大家带来一篇C++对象内存分布详解(包括字节对齐和虚函数表)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 选中多个对象,再用工具栏中的对齐对象工具 和分布对象工具 来调整对象对齐方式和分布方式。  例如,选中3个对象,单击对齐对象工具,选择“左边缘”使3个对象的左边缘对齐,如图1 所示;单击分布对象工具,...
  • 使用候选对象对齐的对象检测.zip
  • Align库允许您将显示对象彼此对齐 计算子显示对象相对于父显示对象的x和y位置。 关系:中心,左,右,上或下 通过传入显示对象或传入数字来进行计算。 如果传入显示对象,则将设置孩子的x和/或y位置。 您可以选择...
  • 使用候选对象对齐的对象检测(2).zip
  • 使用候选对象对齐的对象检测(1).zip
  • 200使用候选对象对齐的对象检测_new.pdf
  • 84使用候选对象对齐的对象检测_new.pdf
  • 15使用候选对象对齐的对象检测_new.pdf
  • cad 单一对象坐标对齐 lisp
  • 对象均布与对齐工具

    2015-05-22 15:07:36
    对象均布与对齐工具,框选对象对齐到边,可预览。
  • office使图表、图片和对象与网格对齐,从而对齐这些对象.docx
  • java对象对齐规则

    千次阅读 2019-09-22 15:52:30
    零、注记 本文是一次讨论的流水账,旨在讲明原理就行了,行文大家不要抱太大的希望。...就是随便实例化一个对象new Object(),他在堆内存里面是怎么放置的。 看下面这个jol工具给出的java.mat...

    零、注记

    本文是一次讨论的流水账,旨在讲明原理就行了,行文大家不要抱太大的希望。

    另外,特别重要的是,本文是基于hotspot来讨论的,不同的java虚拟机可能是有不同的,这一点,一定要注意。

     

    一、什么是对象的内存布局

    简单一句话:对象实例在jvm堆内存中存放的结构。就是随便实例化一个对象new Object(),他在堆内存里面是怎么放置的。

    看下面这个jol工具给出的java.math.BigInteger内存布局的例子:一个对象的内存布局包含了对象头object header、实例数据域和对齐填充alignment padding(可能有,可能没有,下面再细说)。

    ***** 64-bit VM, compressed references enabled: ***************************
    java.math.BigInteger object internals:
     OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
          0    12       (object header)                N/A
         12     4   int BigInteger.signum              N/A
         16     4 int[] BigInteger.mag                 N/A
         20     4   int BigInteger.bitCount            N/A
         24     4   int BigInteger.bitLength           N/A
         28     4   int BigInteger.lowestSetBit        N/A
         32     4   int BigInteger.firstNonzeroIntNum  N/A
         36     4       (loss due to the next object alignment)
    Instance size: 40 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

     

    二、查看对象内存布局的工具

    1. openjdk jol

    openjdk官网给了一个查看对象内存布局的工具,jol(java object layout)http://openjdk.java.net/projects/code-tools/jol/

    怎么拿呢?openjdk给了maven的依赖:

    Use as Library Dependency
    OpenJDK Community semi-regularly pushes the releases to Maven Central. Therefore, you can use it right away by setting up the Maven dependency:
    <dependency>
        <groupId>org.openjdk.jol</groupId>
        <artifactId>jol-core</artifactId>
        <version>put-the-version-here</version>
    </dependency>
    It is a good idea to review JOL Samples and CLI tools source before using the tool at its full capacity as the library.

    怎么用呢?上面给的jol的链接页面,最下面官方给了jol samples的链接,使用极其简单,就是一个ClassLayout就没了。示例就懒得给了,看samples吧。

    jol sampleshttp://hg.openjdk.java.net/code-tools/jol/file/tip/jol-samples/src/main/java/org/openjdk/jol/samples/

    jol sourcecodehttp://central.maven.org/maven2/org/openjdk/jol/

    如果不想看samples呢?这篇参考文章给了用例和讲解《JDK之JVM中Java对象的头部占多少byte》https://my.oschina.net/u/2518341/blog/1838006

    那如果不想用jol工具怎么办呢?卧槽,我好难啊。。。

    2. sun.misc.Unsafe

    • sun.misc.Unsafe.objectFieldOffset方法获取第一个field的偏移地址(弊端:当对象头后面有padding的时候,你看不出来,什么时候有padding呢,下面会细说)
    • JDK8及之前,是用的sun.misc.Unsafe
    • JDK9有两个Unsafe,除了sun.misc.Unsafe还提供了jdk.internal.misc.Unsafe,但是jdk.internal.misc.Unsafe不像sun.misc.Unsafe是可以通过反射使用的,实际上目前在JDK9以后的版本中,sun.misc.Unsafe中组合了jdk.internal.misc.Unsafe的实例,实际上sun.misc.Unsafe是一个简单包装,你可以自己翻翻源码。

    至少有两种方式可以获取到sun.misc.Unsafe实例对象:

    • 通过反射sun.misc.Unsafe的构造函数获取其实例对象;
    • 通过反射sun.misc.Unsafe的实例属性theUnsafe获取其实例对象;
    package cn.wxy.unsafe;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import sun.misc.Unsafe;
    
    public class UnsafeUtils {
    	/**
    	 * 通过反射sun.misc.Unsafe的构造函数获取其实例对象
    	 * 
    	 * @return sun.misc.Unsafe
    	 */
    	public static Unsafe getUnsafeByConstructor() {
    		Constructor<Unsafe> constructor = null;
    		try {
    			constructor = Unsafe.class.getDeclaredConstructor();
    			constructor.setAccessible(true);
    			return constructor.newInstance();
    		} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
    				| IllegalArgumentException | InvocationTargetException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    	/**
    	 * 通过反射sun.misc.Unsafe的属性获取其实例对象
    	 * 
    	 * @return sun.misc.Unsafe
    	 */
    	public static Unsafe getUnsafeByField() {
    		Field field = null;
    		try {
    			field = Unsafe.class.getDeclaredField("theUnsafe");
    			field.setAccessible(true);
    			return (Unsafe) field.get(null);
    		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    }

     

    三、#program pack(n)

    C、C++里面的对齐规则,默认32bit机器是4byte对齐,64比特机器是8byte对齐。那如果想修改默认对齐规则呢?在源码开头写上#program pack(n)声明就行了。

    #program pack(n),n必须是2的次方,这个声明的作用就是告诉编译器使用的对齐方式是n(不管对齐方式n是1byte、2byte、4byte、8byte、16byte还是多少,对齐规则不变,都如下所示),就不再使用默认的对齐方式。

    在C、C++里面的对齐规则如下(链接:https://baike.baidu.com/item/%E5%86%85%E5%AD%98%E5%AF%B9%E9%BD%90/9537460?fr=aladdin):

    规则:

    1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行

    2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行

    3、结合1、2可推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

    众所周知,jvm是C、C++写的,那java默认的8byte对齐规则,和这个一样吗?

    结果是有相同的部分,也有不同的部分:

    • 对象内的对齐规则:对象头、field和padding和第一条规则一致;
    • 对象间的对齐规则:不一样,java默认就是对象间8byte对齐,不管对象头的size、fields中最大的field的size是否小于8byte,如果是16byte,那对象之间就是按照16byte对齐,一样的也不管对象头的size、fields中最大的field的size是否小于16byte。

    第五部分,通过jol会给出两条规则的示例,更多的下面部分再细说。

    补充

    为什么要对齐?1. 效率;2. 有些OS平台有要求。

    参考链接:《Data alignment: Straighten up and fly right》https://developer.ibm.com/articles/pa-dalign/

     

    四、java对象的内存布局

    java对象的内存布局,在周志明的《深入理解java虚拟机》第二章有讲解,三个结构:

    • 对象头:mark word和元数据指针,注意如果是数组对象,其对象头除了mark word和元数据指针之外,还有个4byte int类型的length,本文未讨论数组类型(如果是数组类型,那么对象头加4byte,其他规则不变)。
    • 实例数据域
    • 对齐填充padding

    1. 对象头

    如果你理解hotspot的oop-klass二分模型,那这里你一定了解过。jvm中对象的对象头分为两部分,mark work和元数据指针。

    在hotspot的oop.hpp文件中class oopDesc描述了对象头,链接和源码如下:

    src/share/vm/oops/oop.hpp:http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/oop.hpp

    class oopDesc {
      friend class VMStructs;
     private:
      volatile markOop  _mark;
      union _metadata {
        Klass*      _klass;
        narrowKlass _compressed_klass;
      } _metadata;

    其中,markOop _mark官方文档叫做mark word,union _metadata中的Klass* _klass是元数据指针,指向持久代或者metaspace中每个类的元数据,也就是java.lang.Class类实例访问的jvm中该类的数据结构。

    mark word的内存结构及源码如下,其中在32bit机器上是占4byte,在64bit机器上是8byte,不管是否开启压缩指针-XUseCompressOops。是否开启压缩指针,影响的是元数据指针_klass的size。

    src/share/vm/oops/markOop.hpp:http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/oops/markOop.hpp

    // Bit-format of an object header (most significant first, big endian layout below):
    //
    //  32 bits:
    //  --------
    //             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
    //             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
    //             size:32 ------------------------------------------>| (CMS free block)
    //             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
    //
    //  64 bits:
    //  --------
    //  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)
    //  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)
    //  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
    //  size:64 ----------------------------------------------------->| (CMS free block)
    //
    //  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)
    //  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)
    //  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
    //  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
    //
    //  - hash contains the identity hash value: largest value is
    //    31 bits, see os::random().  Also, 64-bit vm's require
    //    a hash value no bigger than 32 bits because they will not
    //    properly generate a mask larger than that: see library_call.cpp
    //    and c1_CodePatterns_sparc.cpp.
    //
    //  - the biased lock pattern is used to bias a lock toward a given
    //    thread. When this pattern is set in the low three bits, the lock
    //    is either biased toward a given thread or "anonymously" biased,
    //    indicating that it is possible for it to be biased. When the
    //    lock is biased toward a given thread, locking and unlocking can
    //    be performed by that thread without using atomic operations.
    //    When a lock's bias is revoked, it reverts back to the normal
    //    locking scheme described below.
    //
    //    Note that we are overloading the meaning of the "unlocked" state
    //    of the header. Because we steal a bit from the age we can
    //    guarantee that the bias pattern will never be seen for a truly
    //    unlocked object.
    //
    //    Note also that the biased state contains the age bits normally
    //    contained in the object header. Large increases in scavenge
    //    times were seen when these bits were absent and an arbitrary age
    //    assigned to all biased objects, because they tended to consume a
    //    significant fraction of the eden semispaces and were not
    //    promoted promptly, causing an increase in the amount of copying
    //    performed. The runtime system aligns all JavaThread* pointers to
    //    a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))
    //    to make room for the age bits & the epoch bits (used in support of
    //    biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).
    //
    //    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread
    //    [0           | epoch | age | 1 | 01]       lock is anonymously biased
    //
    //  - the two lock bits are used to describe three states: locked/unlocked and monitor.
    //
    //    [ptr             | 00]  locked             ptr points to real header on stack
    //    [header      | 0 | 01]  unlocked           regular object header
    //    [ptr             | 10]  monitor            inflated lock (header is wapped out)
    //    [ptr             | 11]  marked             used by markSweep to mark an object
    //                                               not valid at any other time
    //
    //    We assume that stack/thread pointers have the lowest two bits cleared.

    在64bit机器上,元数据指针的大小是会受压缩类指针是否开启的影响的。32bit机器,元数据指针大小4byte,在64byte机器上,默认是开启压缩指针的(-XX:+UseCompressedClassPointers),开启之后,元数据指针也是4byte,关闭则占8byte。

    补充:

    在Scott oaks写的《java性能权威指南》第八章8.22节提到了当heap size堆内存大于32GB是用不了压缩指针的,对象引用会额外占用20%左右的堆空间,也就意味着要40GB左右的内存才相当于开启了指针压缩的32GB堆空间。

    这是为什么呢?看下面引用中的红字(来自openjdk wiki:https://wiki.openjdk.java.net/display/HotSpot/CompressedOops)。开启压缩指针需要连续的地址空间(进程的虚拟地址空间),其实现原理了是64bit基址+32bit的偏移地址,32bit最大寻址空间是4GB,Java默认8byte对齐,所以开启了压缩指针之后呢,一个地址寻址不再是1byte,而是8byte,因为不管是32bit的机器还是64bit的机器,java对象都是8byte对齐的,而类是java中的基本单位,对应的堆内存中都是一个一个的对象。

    Compressed oops represent managed pointers (in many but not all places in the JVM) as 32-bit values which must be scaled by a factor of 8 and added to a 64-bit base address to find the object they refer to. This allows applications to address up to four billion objects (not bytes), or a heap size of up to about 32Gb. At the same time, data structure compactness is competitive with ILP32 mode.

    你还可以查看jvm中压缩指针参数文档,压缩指针有两个开关——-XX:+UseCompressedOops和-XX:+UseCompressedClassPoints,前者是压缩对象指针,后者是压缩类指针。

    -XX:-UseCompressedOops: 

    Disables the use of compressed pointers. By default, this option is enabled, and compressed pointers are used when Java heap sizes are less than 32 GB. When this option is enabled, object references are represented as 32-bit offsets instead of 64-bit pointers, which typically increases performance when running the application with Java heap sizes less than 32 GB. This option works only for 64-bit JVMs.

    It is also possible to use compressed pointers when Java heap sizes are greater than 32GB. See the -XX:ObjectAlignmentInBytes option.

    为什么坚持8byte对齐呢?Scott oaks在书上给了理由:

    2. 实例数据域

    实例数据域紧跟在对象头之后。一个类没有field,就不需要实例数据域,有那就按照第三部分#program pack对齐规则的第一条放在堆内存中。这部分在第五部分,给出jol的示例详细讨论其规则。

    3. padding

    对象内可以有padding也可以没有;对象间默认按照8byte对齐,对齐则不需要padding,否则需要padding补充8byte对齐,也在第五部分根据jol的示例详细讨论其规则。

     

    五、java的对齐规则

    1. 对象内的对齐规则:对象头、field和padding和#program pack第一条规则一致;
      1. 注意:对象头默认是没有padding的,是否需要padding,要看是32bit机器还是64bit机器,以及对象头后面跟的field size,这是#program pack的对齐规则导致的padding,而不是对象头导致padding,这一点看过很多人讨论错了。
    2. 对象间的对齐规则:不一样,java的对象间对齐如果是按照8byte,那就是8byte,不会再像#program pack中还需要和对象内最大size的属性比较;
      1. 解释:java默认就是对象间8byte对齐,不管对象头的size、fields中最大的field的size是否小于8byte;如果是16byte,那对象之间就是按照16byte对齐,一样的也不管对象头的size、fields中最大的field的size是否小于16byte。
      2. -XX:ObjectAlignmentInBytes=alignment:你可以通过这个JVM参数修改对象的对齐方式

     

    -XX:ObjectAlignmentInBytes=alignment

    Sets the memory alignment of Java objects (in bytes). By default, the value is set to 8 bytes. The specified value should be a power of two, and must be within the range of 8 and 256 (inclusive). This option makes it possible to use compressed pointers with large Java heap sizes.

    The heap size limit in bytes is calculated as:

    4GB * ObjectAlignmentInBytes

    Note: As the alignment value increases, the unused space between objects will also increase. As a result, you may not realize any benefits from using compressed pointers with large Java heap sizes.

    补充:前四个例子均来源于jol官网示例,我感觉足够说明了,就懒得动手了,第五个需要动手搞一下,但是我也没动手 ,直接用了和群友讨论的例子。感觉足够说明了,就偷懒取巧不动手了。

    例一、32bit机器的对象内存布局(默认对象间8byte对齐)

    ***** 32-bit VM: **********************************************************
    $ java -jar jol-cli/target/jol-cli.jar estimates java.math.BigInteger
    java.math.BigInteger object internals:
     OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
          0     8       (object header)                N/A
          8     4   int BigInteger.signum              N/A
         12     4 int[] BigInteger.mag                 N/A
         16     4   int BigInteger.bitCount            N/A
         20     4   int BigInteger.bitLength           N/A
         24     4   int BigInteger.lowestSetBit        N/A
         28     4   int BigInteger.firstNonzeroIntNum  N/A
    Instance size: 32 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

    32bit机器上,对象头8byte,其中,mark word 4byte,元数据指针4byte。

    java.math.BigInteger有6个成员属性field,都是4byte(5个int基本数据类型每个4byte;一个int[]数组引用类型,这里其实保存的是指针,因为数组本身就是一个引用类型,所以在堆内存中还有自己对象结构,因此在本例BigInteger中的int[]其实是一个4byte指针),按照4byte对齐,对象头0~7byte,后面的每个field的起始地址都是4byte的整倍数,不需要额外的padding来对齐。

    对象大小:object header(mark word+metadata klass)+6*field = 8byte+4*6byte =32byte。

    因为32byte % 8byte= 0,所以对象间不需要额外的padding来帮助对齐。

     

    例二、64bit机器的对象内存布局(默认对象间8byte对齐,没有开启指针压缩)

    ***** 64-bit VM: **********************************************************
    java.math.BigInteger object internals:
     OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
          0    16       (object header)                N/A
         16     8 int[] BigInteger.mag                 N/A
         24     4   int BigInteger.signum              N/A
         28     4   int BigInteger.bitCount            N/A
         32     4   int BigInteger.bitLength           N/A
         36     4   int BigInteger.lowestSetBit        N/A
         40     4   int BigInteger.firstNonzeroIntNum  N/A
         44     4       (loss due to the next object alignment)
    Instance size: 48 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    64bit机器,未开启指针压缩,对象头16byte,其中mark word 8byte,元数据指针8byte。

    java.math.BigInteger有6个成员属性,其中int[] BigInteger.mag是引用类型,未开启指针压缩占8byte,剩下5个int各占4byte,对象头0~15byte,mag 8byte对齐,占16~23,剩下的5个4byte对齐,对象内不需要额外的padding对齐。

    对象大小:16byte+8byte+5*4byte = 44byte。

    因为44byte%8byte = 4byte,所以按照8byte对齐,对象间还需要额外的4byte来帮助对齐。

    所以,对象真正占用的内存是44byte + 4byte = 48byte。

     

    例三、64bit机器并开启压缩指针的对象内存布局(默认对象间8byte对齐)

    ***** 64-bit VM, compressed references enabled: ***************************
    java.math.BigInteger object internals:
     OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
          0    12       (object header)                N/A
         12     4   int BigInteger.signum              N/A
         16     4 int[] BigInteger.mag                 N/A
         20     4   int BigInteger.bitCount            N/A
         24     4   int BigInteger.bitLength           N/A
         28     4   int BigInteger.lowestSetBit        N/A
         32     4   int BigInteger.firstNonzeroIntNum  N/A
         36     4       (loss due to the next object alignment)
    Instance size: 40 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

    64bit机器开启指针压缩,对象头12byte,其中mark word 8byte,元数据指针4byte。

    java.math.BigInteger 6个成员属性,因为开启了指针压缩,所以例二中的int[] BigInteger.mag不再占用8byte,而是4byte,其他5个成员属性int各占4byte。对象头12byte,每个成员属性按照4byte对齐,对象内不需要额外的padding来帮助对齐。

    对象大小:12byte + 6*4byte = 36byte。

    因为36byte % 8byte = 4byte,按照8byte对齐,所以对象间还需要额外的4byte来帮助对齐。

    所以对象真正占用的内存大小:36byte + 4byte = 40byte。

     

    例四、64bit机器并开启压缩指针、修改按照16byte对齐

    ***** 64-bit VM, compressed references enabled, 16-byte align: ************
    java.math.BigInteger object internals:
     OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
          0    12       (object header)                N/A
         12     4   int BigInteger.signum              N/A
         16     4 int[] BigInteger.mag                 N/A
         20     4   int BigInteger.bitCount            N/A
         24     4   int BigInteger.bitLength           N/A
         28     4   int BigInteger.lowestSetBit        N/A
         32     4   int BigInteger.firstNonzeroIntNum  N/A
         36    12       (loss due to the next object alignment)
    Instance size: 48 bytes (estimated, the sample instance is not available)
    Space losses: 0 bytes internal + 12 bytes external = 12 bytes total

    对象按16byte对齐,也就意味着对象放到堆中的时候,其起始地址模16必须为0,即address % 16byte = 0。

    对象头和例三一样,12byte。

    开启指针压缩,对象内6个属性也都是4byte,对象内各个属性按照4byte对齐,不需要额外的padding。

    对象大小:12byte + 6*4byte = 36byte。

    因为36byte % 16byte = 4byte,为了模16byte为0,对象间还需要额外的12byte来帮助对齐(12byte + 4byte = 16byte)。

    所以对象真正占用的的内存大小:36byte+12byte(对象间的alignment)=48byte。

     

    例五、对象头是否需要padding

    这个对比例子中,java.lang.Integer对比java.lang.Long。Integer中只有一个private final int value的对象,Long中只有一个private final long value属性(就是JDK的源码)。

    环境:64bit机器开启压缩指针,默认按照8byte对齐。

    Integer的例子中,对象头12byte,属性int value 4byte并按照4byte对齐,所以最终对象大小16byte。对象内的属性int value起始地址12,所以对象内不需要额外的padding,对象大小16byte,是8byte的整倍数,所以对象间也不需要额外的padding来对齐。

    Long的例子中,对象头12byte,long value是8byte并按照8byte对齐,而对象头12byte从0byte~11byte,所以Long的实际存放地址是16~23byte,在long value和对象头之间需要4byte的padding(但这个padding不是对象头的,是后面的long value根据第一条对齐规则导致的,Integer例子中int value是4byte对齐,就不需要额外的padding)。填充之后,对象大小为24byte,是默认对齐8byte的整倍数,对象间不需要额外的padding。

     

    六、附注

    以上就是根据表象推断出来的java的对齐规则。可能有遗漏,甚至有错误,欢迎指正,欢迎留言讨论!

    展开全文
  • 摘要:C#源码,字符处理,RichTextBox C#设置RichTextBox的文本对齐方式,实例需引用命名空间Using System.IO,本例的一些相关操作:从指定的位置加载并保存RTF文件、清空RichTextBox控件中的所有内容、设定“保存”...
  • JVM对象创建和对齐填充详解

    千次阅读 2021-03-04 10:58:42
    1.虚拟机对象创建 ​ 语言层面上,创建对象通常(例外:复制、反序列化)仅仅是一个new关键字而已,本文所探讨的虚拟机对象创建不包含数组和Class...划分空间两种方式 指针碰撞,堆内存规整 所代表的垃圾收集器有

    1.虚拟机对象创建

    ​ 语言层面上,创建对象通常(例外:复制、反序列化)仅仅是一个new关键字而已,本文所探讨的虚拟机对象创建不包含数组和Class对象等,就对于普通对象而言。

    1. 常量池中定位符号引用

      • Java虚拟机遇到一条字节码new指令时,检查指令的参数能否在常量池中定位一个符号引用。
    2. 检查类是否被加载

      • 检查这个符号引用代表的类是否已被加载、解析和初始化过。
    3. 类加载过程

      • 确定所加载类占用内存大小,并划分空间进行存储
      • 划分空间两种方式
        • 指针碰撞,堆内存规整
          • 所代表的垃圾收集器有Serial、ParNew,用算法标记-整理算法
          • 可能导致线程不安全问题,可看下方tip1:指针碰撞所带来的线程安全问题。
        • 空闲列表
          • 所代表的垃圾收集器CMS,采用标记清除算法
      • 对象设置
        • 虚拟机还要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码对象的GC分代年龄等信息。。这些信息存放在对象的对象头(Tip2:对象都存储内容)之中。

      上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始——构造函数,即Class文件中的()方法还没有执行,所有的字段都为默认的零值。梳理完虚拟机对象创建过程后,在来看看对象在堆内存的存储布局.

    2.对象的内存布局

    在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

    2.1对象头

    HotSpot虚拟机对象的对象头部分包括两类信息:

    1. 第一类是用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,官方称它为“Mark Word”。
    2. 第二类类型指针

    2.2实例数据

    ​ 实例数据部分是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。这部分的存储顺序会受到虚拟机分配策略参数(-XX:FieldsAllocationStyle参数)和字段在Java源码中定义顺序的影响。

    ​ HotSpot虚拟机默认的分配顺序为longs/doublesintsshorts/charsbytes/booleans、oops。

    ​ 从以上默认的分配策略中可以看到,相同宽度的字段总是被分配到一起存放,在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。

    ​ 对象的第三部分是对齐填充,这并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。

    2.3对齐填充

    ​ 由于HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。对象头部分已经被精心设计成正好是8字节的倍数(1倍或者2倍),因此,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

    ​ 总的一句话来说,“数据项仅仅能存储在地址是数据项大小的整数倍的内存位置上(分别为偶地址、被4整除的地址、被8整除的地址)”比如int类型占用4个字节,地址仅仅能在0,4,8等位置上。

    ​ 要讲好对齐填充,其实还是得去了解c++实现。

    例1:

    #include <stdio.h>
    struct xx{
        char b;
        int a;
        int c;
        char d;
    };   //总体结构用了16个字节
    
    struct xx{
            char b; 
            char d;
            int a;          
            int c;                  
    };	//总体结构占用12个字节
    

    只说结论,过程可以将对应得字段地址打印出来。

    会发现b之后填充3字节,d之后也会填充3字节,这儿就体现了对齐填充,平时代码,分类要做好,对齐填充也要注意。

    Tip1:指针碰撞所带来的线程安全问题。

    ​ 对象创建在虚拟机中是非常频繁的行为,即使仅仅修改一个指针所指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。解决这个问题有两种可选方案:

    1. 一种是对分配内存空间的动作进行同步处理——实际上虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性;
    2. 另外一种是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local AllocationBuffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步处理。虚拟机是否使用TLAB,可以通过-XX:+/-UseTLAB参数来设定。

    Tip2:对象头存储内容

    对象头又称"Mark Word"。定义了一个有着动态数据的数据结构例如在32位的HotSpot虚拟机中,如对象未被同步锁锁定的状态下,Mark Word的32个比特存储空间中的25个比特用于存储对象哈希码4个比特用于存储对象分代年龄2个比特用于存储锁标志位1个比特固定为0,在其他状态(轻量级锁定、重量级锁定、GC标记、可偏向)下对象的存储内容如表2-1所示。

    在这里插入图片描述

    对象头的另外一部分是类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针来确定该对象是哪个类的实例。

    展开全文
  • 对齐所有选定的对象都与选择中的最后一个对象对齐。 因此必须至少选择两个对象。 对特定的对齐线进行对齐。 它们是矩形图形对象的左侧、右侧、顶部、底部、水平中心和垂直中心以及连接点的中心。 2. 复印尺寸最后...
  • word启用或关闭对齐网格和对齐对象选项.docx
  • 具有潜在特征对齐和过滤功能以进行对象检测的子类别聚类
  • C++之:类对象内存对齐

    千次阅读 2016-03-26 09:55:02
    一、关于空间的思考一个Class对象需要占用多大的内存空间。最权威的结论是: *非静态成员变量总合。(not static) *加上编译器为了CPU计算,作出的数据对齐处理。(c语言中面试中经常会碰到内存对齐的问题) *...

    一、关于空间的思考

    一个Class对象需要占用多大的内存空间。最权威的结论是:

    *非静态成员变量总合。(not static)

    *加上编译器为了CPU计算,作出的数据对齐处理。(c语言中面试中经常会碰到内存对齐的问题)

    *加上为了支持虚函数(virtual function),产生的额外负担。

    二、例程

    //注:以下注释是在mac os g++ 环境编译:g++ memAlign.cpp -o memAlign
    
    //size = 1
    //1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);
    class Car1{
    };
    void fun1(void)
    {
        int size =0;
        Car1 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car1 Size",size);
    }
    
    //size = 8
    class Car2{
    private:
        int nLength;
        int nWidth;
    };
    void fun2(void)
    {
        int size = 0;
        Car2 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car2 Size",size);
    }
    
    //size = 8
    //2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;
    class Car3{
    private:
        int nLength;
        int nWidth;
        static int sHight;
    };
    void fun3(void)
    {
        int size =0;
        Car3 objCar;
        size =sizeof(objCar);
        printf("%s is %d\n","Class Car3 Size",size);
    }
    
    //size = 12
    //3、因此一个对象的大小≥所有非静态成员大小的总和;
    class Car4{
    private:
        char chLogo;
        int nLength;
        int nWidth;
        static int sHigh;
    };
    void fun4(void)
    {
        int size =0;
        Car4 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car4 Size",size);
    }
    
    //size = 1
    class Car5{
    public:
        Car5(){};
        ~Car5(){};
    public:
        void Fun(){};
    };
    void fun5(void)
    {
        int size =0 ;
        Car5 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car5 Size",size);
    }
    
    //size = 8
    class Car6{
    public:
        Car6(){};
        ~Car6(){};
    public:
        void Fun(){};
    private:
        int nLength;
        int nWidth;
    };
    void fun6(void)
    {
        int size = 0;
        Car6 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car6 Size",size);
    }
    
    //size = 8
    //4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
    class Car7{
    public:
        Car7(){};
        virtual ~Car7(){};
    public:
        void Fun(){};
    };
    void fun7(void)
    {
        int size = 0;
        Car7 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car7 Size",size);
    }
    
    //size = 8
    class Car8{
    public:
        Car8(){};
        virtual ~Car8(){};
    public:
        void Fun(){};
        virtual void Fun1(){}
    };
    void fun8(void)
    {
        int size = 0;
        Car8 objCar;
        size = sizeof(objCar);
        printf("%s is %d\n","Class Car8 Size",size);
    }
    
    //5、虚继承的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr(virtual function table)指针指向虚函数表vfTable和一个vbPtr(virtual base pointer)指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);
    
    //6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;(请参考《c和指针》)
    
    //7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。
    
    int main()
    {
        fun1();
        fun2();
        fun3();
        fun4();
        fun5();
        fun6();
        fun7();
        fun8();
    }

    在VC6.0 下输出:

    Class Car1 Size is 1
    Class Car2 Size is 8
    Class Car3 Size is 8
    Class Car4 Size is 12
    Class Car5 Size is 1
    Class Car6 Size is 8
    Class Car7 Size is 4 //不同
    Class Car8 Size is 4 //不同

    主要的不同点是:在Car7和Car8,在VC 6.0中虚函数指针占用4个字节,在gcc编译器中占用8个字节。

    个人认为和平台位数对齐有关,而不是单纯的编译器有关
    (原文:也可以换一种说法是virtual函数指针在VC下以4字节对齐,在gcc下是8字节对齐,这样解释就比较清楚了。)

    三、编程实现成员在类或结构体中的偏移量

    #include <cstdio>
    #include <iostream>
    #define pos(type,member) (&((type *)0)->member)
    
    class car{
    public:
        car(){}
        ~car(){}
    public:
        virtual void fun(){}
    private:
        int c;
    public:
        void print()
        {
            printf("%x\n",pos(car,c));
        }
    };
    
    int main()
    {
        struct Node{
            int a ;
            char b;
            int c;
        };
        car objCar;
    //    printf("%x\n",&((struct Node *)0)->b);
        printf("%x\n",pos(struct Node,b));
        printf("%x\n",pos(struct Node,c));
    //    printf("%x\n",pos(class car,c));
        objCar.print();
        return 0;
    }

    其中关键的是找到函数能够实现计算成员在类中的偏移量,这里用了宏来实现的。

    #define pos(type,member) (&((type *)0)->member)

    (从地址0开始的一个type结构体或者类,其成员的地址就是成员所在类或结构体的偏移量)

    上述程序的输出结果就是: 4 8 8


    参考文献

    [1] http://www.cnblogs.com/xuanyuanchen/archive/2012/10/24/2737626.html

    [2] http://blog.csdn.net/hackbuteer1/article/details/7883531

    展开全文
  • 上一篇文章我们讲解了JVM对象内存布局的第一部分对象头,今天我们继续来讲讲剩下的两部分实例数据(Instance Data) 、对齐填充(Padding)。 实例数据与对齐填充 这两部分我们放在一起将,先来看一下概念(深入理解...
  • PowerPoint2021对齐多个对象方法.docx
  • C11中提供了 查看 和 自定义 对象字节对齐方式的方法. 关于字节对齐见这里 查看对象字节对齐方式: _Alignof 操作符 用法: _Alignof(typename) 返回size_of类型的typename类型对象对齐方式...
  • 在PowerPoint2021中对齐所选对象.docx
  • //右边左对齐 //左边右对齐 //上边下对齐 //下边上对齐 if (_endAngle > 45 && _endAngle ) lengthText->setAlignment(osgText::Text::CENTER_TOP); else if (_endAngle > 135 && _endAngle ) lengthText...
  • 默认的情况是图片顶对齐而文字底对齐,通过设置css属性可以使得图片与文字对齐,接下来为大家详细介绍下设置各对象的vertical-align属性,感兴趣的朋友可以参考下哈
  • 一组工具,可轻松将网格与世界轴对齐或将局部对象轴与网格对齐 工具 此附加组件包括两个实用程序运算符,它们包装在一个简单的面板中: 将边缘与X轴对齐 旋转对象,以使选定的边缘与给定的全局轴对齐。 用法:恰好...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 212,277
精华内容 84,910
关键字:

对象的对齐方式主要