精华内容
下载资源
问答
  • 使用候选对象对齐的对象检测.zip
  • 使用候选对象对齐的对象检测(1).zip
  • 使用候选对象对齐的对象检测(2).zip
  • 200使用候选对象对齐的对象检测_new.pdf
  • 84使用候选对象对齐的对象检测_new.pdf
  • 15使用候选对象对齐的对象检测_new.pdf
  • AutoCad对象对齐,均布对象工具,包括左对齐、居中对齐,右对其,上对其、下对齐等6种对其方式,此外还有指定点对其,指定对象对齐,均布工具有垂直均布、水平均布等8种均布方式,还包括指定间距均布,制定范围均布...
  • 将 2D 线对象 LINE_OBJ 捕捉到以下约束之一 - 一种。 另一组线路。 湾定义的网格。 C。 鼠标光标(无约束)。
  • 对象均布与对齐工具

    2015-05-22 15:07:36
    对象均布与对齐工具,框选对象对齐到边,可预览。
  • cad 单一对象坐标对齐 lisp
  • office使图表、图片和对象与网格对齐,从而对齐这些对象.docx
  • 选中多个对象,再用工具栏中的对齐对象工具 和分布对象工具 来调整对象对齐方式和分布方式。  例如,选中3个对象,单击对齐对象工具,选择“左边缘”使3个对象的左边缘对齐,如图1 所示;单击分布对象工具,...
  • C语言中, 每个完整的对象都具有字节对齐要求. 比如基本数据类型一般参照类型本身大小字节对齐, char类型对象按1字节对齐, short类型按2字节对齐等. C11中提供了 查看 和 自定义 对象字节对齐方式的方法. 关于字节...

    C语言中, 每个完整的对象都具有字节对齐要求. 比如基本数据类型一般参照类型本身大小字节对齐, char类型对象按1字节对齐, short类型按2字节对齐等. C11中提供了 查看自定义 对象字节对齐方式的方法. 关于字节对齐见这里

    • 查看对象字节对齐方式: _Alignof 操作符

      • 用法: _Alignof(typename) 返回size_of类型的typename类型对象的对齐方式. _Alignof(char) 返回1, 表示char类型对象按1字节对齐.
      • 注意:
        (1) 引用 stdalign.h 头文件后可以直接使用_Alignof对应的宏 alignof
        (2) typename 可以是基本类型 枚举类型 结构体 联合体等, 但是必须是类型名(这里存疑, 使用对象名也可以)
        (3) 可以使用 alignof(max_align_t) 获取当前实现支持的最大对齐方式
    • 自定义对象字节对齐方式: _Alignas 操作符

      • 用法:
        (1) _Alignas(typename) 将对象声明为按 Alignof(_typename) 大小对齐方式对齐. 比如 char _Alignas(int) ch; ch按_Alignof(int)大小对齐.
        (2) _Alignas(expression) 将对象声明为按 expression 大小对齐方式对齐. 比如 char _Alignas(4) ch; ch按4字节大小对齐.
      • 注意:
        (1) 引用 stdalign.h 头文件后可以直接使用_Alignas对应的宏 alignas
        (2) _Alignas操作数指定的字节对齐大小不能小于当前实现默认的对齐大小
        (3) _Alignas操作数应该是0, 1, 2, 4或4的倍数等无符号整数, 但不能超过max_align_t的大小
        (4) _Alignas(0)表示按默认对齐方式对齐
    // 自定义字节对齐方式
    #include <sdtio.h>
    #include <stdalign.h>
    #include <stddef.h>
    
    int main()
    {
        // 查看字节对齐方式
        size_t size = _Alignof(max_align_t);
        printf("当期实现支持的最大字节对齐方式: %zu\n", size);
        size = alignof(int);
        printf("int类型对象默认字节对齐方式: %zu\n", size);
    
        // 自定义字节对齐方式
        size = alignof(char);
        printf("char类型对象默认字节对齐方式: %zu\n", size);
        char _Alignas(int) ch = 'a';
        size = alignof(ch);
        printf("char类型对象ch自定义字节对齐方式: %zu\n", size);
    
        // 选择选项中最大的字节对齐方式
        int alignas(32) alignas(64) alignas(int) n = 0;
        size = alignof(n);
        printf("int类型对象n自定义字节对齐方式: %zu\n", size);
    
        return 0;
    }
    展开全文
  • 对齐所有选定的对象都与选择中的最后一个对象对齐。 因此必须至少选择两个对象。 对特定的对齐线进行对齐。 它们是矩形图形对象的左侧、右侧、顶部、底部、水平中心和垂直中心以及连接点的中心。 2. 复印尺寸最后...
  • 精确工作空间设计:FME2018.1中...FME2018.1已经推出,我想做一个关于FME工作空间画布对象对齐的简介。 为什么?因为我们做了一些小的改变,如果你是像我这样的工作空间设计完美主义者时,可能有所帮助。 但是首先...

    精确工作空间设计:FME2018.1中画布对象的对齐

    原文地址:https://blog.safe.com/2018/08/object-alignment-workbench-evangelist175/

    https://cdn.blog.safe.com/wp-content/uploads/2018/05/29125056/AligningObjects0.png

    FME2018.1已经推出,我想做一个关于FME工作空间画布对象对齐的简介。

    为什么?因为我们做了一些小的改变,如果你是像我这样的工作空间设计完美主义者时,可能有所帮助。

    但是首先,先来看看我说的对齐是什么以及为什么你需要关注……

     

    为什么对齐对象?

    我们都知道如果工作空间组织得当,工作空间看起来会更好。事实上,在Safe最受欢迎的说法是:

    一个外观漂亮,组织良好的工作空间让客户感觉您已经完成了高质量的工作。

    漂亮的工作空间包括对齐对象,比如在画布中的转换器。

    我希望你能同意这点……

     

    简单对齐有很大改进:

     

    每列转换器沿中心对齐,每行沿顶部对齐,转换器均匀分布,两个书签右对齐。也许你没有注意到——FeatureJoiner的顶部与StringReplacer顶部对齐,并且“Creator Join Key”这个注释也在列/行布局中对齐。

     

    这样的布局看起来需要很多工作,但创建这样的布局并不难……

     

    如何对齐画布对象

    在工作画布中对齐对象需要先选中它们,然后从工具栏中选择选项,或者快捷菜单:

    说明: Alignment tools on the context menu

    由于三个选定的变换器都在一列中,因此我使用左对齐(Left),中间(Middle)或右对齐(Right)选项对它们进行排列。然后我将使用“Vertically”(垂直展开)选项将它们均匀分隔。

     

    对于第二列我重复上述操作,然后对每行的转换器进行操作,使用“顶部对齐(Align Left)”,“中心(Middle)”或“底部(Bottom)”进行对齐,并使用“Horizontally(水平展开)”进行间距处理。

     

    注意这不仅仅针对转换器;我可以对书签也使用相同的对齐工具。

     

    为了避免每次使用快捷菜单,你可以添加快捷键到工具栏(Tools > FME Options > Toolbar):

    顺便说一下,右侧选项为自动布局;但是我很少使用……好吧,我是一个喜欢手工制作自己的工作空间的GeoHipster

     

    不管怎样,我们可以通过这种方式对齐对象。但是我们如何选择“关键对象”呢?

    关键对象对齐

    什么是关键?好好想象使用Snapper的对齐操作的对齐方式:

    说明: https://cdn.blog.safe.com/wp-content/uploads/2018/05/29104829/AligningObjects5.png

    这两条线需要在此处捕捉,但是这样需要选择哪条线保持不动,哪条线进行捕捉操作。如果这个很重要,你需要使用AnchoredSnapper来锚定其中的一条线。

    同样的事情使用于Workbench等图形界面中的布局工具。转换器A对齐到转换器B,或转换器B对齐到转换器A?在捕捉操作中的“锚点”即图形界面中的“关键(key)”。

    所以我如何选择FME Workbench中的关键?有两种方法。第一个办法是在关键对象上选择快捷菜单:

    说明: https://cdn.blog.safe.com/wp-content/uploads/2018/05/29105702/AligningObjects6.png

    在这里,因为我在Aggregator转换器上右键单击,它就成为关键对象,AttributeValueMapper转换器将进行移动:

    说明: https://cdn.blog.safe.com/wp-content/uploads/2018/05/29110119/AligningObjects7.png

    这个功能在FME中已经有一段时间了(你是否注意到了呢?)FME2018.1的新特性体现在你使用工具栏按钮的时候。

    当你使用工具栏对齐对象,你无法在关键对象上单击。而是依次选择每个对象,确保关键对象在最后被选中。所以如果我想在书签种对齐这些对象,请按编号顺序单击(或按住ctrl +单击):

    说明: https://cdn.blog.safe.com/wp-content/uploads/2018/05/29110952/AligningObjects8.png

     

    FME转换器1,2以转换器3为关键对象进行对齐:

    说明: https://cdn.blog.safe.com/wp-content/uploads/2018/05/29111450/AligningObjects9.png

    如果我最后选择的是StringReplacer,另外两个转换器将向左移动与之对齐。

    如果你很聪明,你现在可能正在思考如何在使用批量选择对象时选择关键对象。 这将是一个两步的过程。 首先,您框选所有对象,然后按住Ctrl键并单击关键对象两次(一次取消选择它,一次再次选择它)。虽然这个方法不是很好,但我目前没有了解到其他方式。

     

    对齐总结

    上述博客内容只是为了覆盖一个小更新,当然,大部分原因是覆盖对象对齐。此外,如果在构建过程中使用工作区使用网格和向导来对齐对象,那么这一点就不太必要了。

    但是,如果您继承了未正确组织的工作空间,或者您希望一次对齐多个对象,那么对齐选项是一个很好的工具。

    我希望你发现这个更新很有用。 当你是一个精确的工作空间设计师时,有时它确实是重要的小事。

    展开全文
  • 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

    展开全文
  • Align库允许您将显示对象彼此对齐 计算子显示对象相对于父显示对象的x和y位置。 关系:中心,左,右,上或下 通过传入显示对象或传入数字来进行计算。 如果传入显示对象,则将设置孩子的x和/或y位置。 您可以选择...
  • 选中多个对象,再用工具栏中的对齐对象工具 和分布对象工具 来调整对象对齐方式和分布方式。  例如,选中3个对象,单击对齐对象工具,选择“左边缘”使3个对象的左边缘对齐,如图1 所示;单击分布对象工具,...
  • 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的对齐规则。可能有遗漏,甚至有错误,欢迎指正,欢迎留言讨论!

    展开全文
  • 对于多边形挤出物体,其重心位置可能不在物体中心,此时需要首先调整物体轴心到中心,...2,然后再进行对齐,注意对齐是先选中被对齐的物体,然后在长按对齐方式弹出如下图的对齐选项,选择参考物体,即可对齐: ...
  • 草图插件可按对象的质心对齐对象。 在许多情况下,Magic Aligner可以自动进行光学调整。 查看我在我的网站上写。 安装 并解压缩,然后打开.sketchplugin文件进行自动安装。 用法 通过边框将对象居中 选择一个对象 ...
  • 一. 前言 这篇文章主要介绍以下从c的结构体变量到c++的类对象中编译器对内存分配做的事情。... 为了方便描述,我们按照以下几个层次来讲述: 1.c中struct的字节对齐  2.从struct到class的过渡
  • 首先知道上图左边的圆形对象处在哪一层(如果不知道可以show element),在options面板选择该对象所在的层(如果层选择的不对,下面中心对齐操作无效): 按自定义的change快捷键4,选中图一中的右边,右键,选择...
  • PowerPoint2021对齐多个对象方法.docx
  • 自然对齐是指基本类型变量在内存中的起始地址可以被他们的大小整除,对于复合类型的对象,如果它的起始地址能够满足其中要求最高的数据成员的自然对齐要求,那么它也是自然对齐的。 所以编译器在编译时会对ADT...
  • 在PowerPoint2021中对齐所选对象.docx
  • ​ 语言层面上,创建对象通常(例外:复制、反序列化)仅仅是一个new关键字而已,本文所探讨的虚拟机对象创建不包含数组和Class对象等,就对于普通对象而言。 常量池中定位符号引用 Java虚拟机遇到一条字节码new...
  • 复选框后边一句文字,如何让它们两个并排对齐,相差几个像素的问题,但各个浏览器就是不一样,特别是ie6,经测试解决方法如下,有类似问题的朋友可以参考下
  • 原文:... 对齐]命令,弹出[对齐]窗口。 2. 3. 接着选择左上角的蜜蜂对象。 4. 然后按下键盘上的[Shift]快捷键。 5. 在按下键盘上的该快捷键的同时,点击其它对象,可以依次选择多个对象。 6....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 191,467
精华内容 76,586
关键字:

对象对齐