当前位置: 首页 > news >正文

律师网站建设东莞网络营销优化

律师网站建设,东莞网络营销优化,网站推广方案中,个人做淘宝客网站要备案吗先来了解一下数组对象在堆中的存储形式【数组长度,数组元素类型信息等】 【存放元素对象的空间】 Ma 基础信息实例数据内存填充Mark Word,ClassPointer,数组长度第一个元素第二个元素固定的填充内容 所以我们想要获取某个下标的元素首先要获取这个元素的起始位置…

先来了解一下数组对象在堆中的存储形式【数组长度,数组元素类型信息等】+ 【存放元素对象的空间】

Ma

基础信息实例数据内存填充
Mark Word,ClassPointer,数组长度第一个元素第二个元素固定的填充内容

所以我们想要获取某个下标的元素首先要获取这个元素的起始位置和每个元素长度

例如我们要取第二个元素的,首先知道第二个元素的起始位置,从其实位置开始按照每个元素的长度取指定的位数,就相当于获取了第二个元素的全部信息。

再来了解一下Java中一个特殊的类sun.misc.Unsafe

sun.misc.Unsafe是JDK提供的用于很底层编程的类,位于sun.misc包中。在有些底层编程的场景,Java语言层面办不到的事情,我们可能需要使用JNI,借助C语言去实现。但是使用JNI并不是唯一的选择,使用JNI会将代码绑定到特定的平台,使用Unsafe类可以保留Java语言代码对平台的独立性,又实现底层编程。

Unsafe类并没有public的构造函数,只提供了一个静态工厂方法,这个静态方法还只提供给JDK标准库自身的类调用,在我们自己随便建的一个普通的类调用这个静态工厂方法还会抛异常。

这个静态工厂方法的代码如下:

@CallerSensitive
public static Unsafe getUnsafe() {Class<?> caller = Reflection.getCallerClass();if (!VM.isSystemDomainLoader(caller.getClassLoader()))throw new SecurityException("Unsafe");return theUnsafe;
}

可以使用反射的方式

import sun.misc.Unsafe;
import java.lang.reflect.Field;public class TestUnsafe {private static Unsafe unsafe;static {try {Field f = Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible(true);unsafe = (Unsafe) f.get(null);} catch (Exception e) {//}}}

 Unsafe功能列表

  • allocateMemory/freeMemory,分配、释放堆外内存DirectMemory(和c/cpp中的malloc一样)
  • CAS操作
  • copyMemory
  • defineClass(without security checks)
  • get/put address 使用堆外内存地址进行数据的读写操作
  • get/put volatile 使用堆外内存地址进行数据的读写操作 - volatile版本
  • loadFence/storeFence/fullFence 禁止指令重排序
  • park/unpark 阻塞/解除阻塞线程

Unsafe的数组操作

unsafe中,有两个关于数组的方法:

public native int arrayBaseOffset(Class<?> arrayClass);
public native int arrayIndexScale(Class<?> arrayClass);

arrayBaseOffset 数组第一个元素相对于数组对象起始地址的偏移量

arrayIndexScale就是指数组中每个元素所占用的空间大小,比如int[] scale就是4,long[] scale就是8,object[] scale就是4(指针大小)

// Unsafe mechanicsprivate static final sun.misc.Unsafe U;private static final long SIZECTL;private static final long TRANSFERINDEX;private static final long BASECOUNT;private static final long CELLSBUSY;private static final long CELLVALUE;private static final long ABASE;private static final int ASHIFT;static {try {U = sun.misc.Unsafe.getUnsafe();Class<?> k = ConcurrentHashMap.class;SIZECTL = U.objectFieldOffset(k.getDeclaredField("sizeCtl"));TRANSFERINDEX = U.objectFieldOffset(k.getDeclaredField("transferIndex"));BASECOUNT = U.objectFieldOffset(k.getDeclaredField("baseCount"));CELLSBUSY = U.objectFieldOffset(k.getDeclaredField("cellsBusy"));Class<?> ck = CounterCell.class;CELLVALUE = U.objectFieldOffset(ck.getDeclaredField("value"));Class<?> ak = Node[].class;ABASE = U.arrayBaseOffset(ak);int scale = U.arrayIndexScale(ak);if ((scale & (scale - 1)) != 0)throw new Error("data type scale not a power of two");ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);} catch (Exception e) {throw new Error(e);}}

这是CurrentHashMap中的源码我们需要注意的地方有:

Class<?> ak = Node[].class; 
ABASE = U.arrayBaseOffset(ak);
ABASE:数组第一个元素相对于数组对象起始地址的偏移量
int scale = U.arrayIndexScale(ak);数组中每个元素所占用的空间大小,返回的是所占空间的字节数
scale为2的n次方,2的n次方二进制表示就是某个位置为1其余位置为0
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
Integer.numberOfLeadingZeros(scale) 计算int型参数二进制表示数值最高位前面有几个0
由于int一共有32位,出去位1的一位剩下31位,31 - Integer.numberOfLeadingZeros(scale)就表示scale二进制表示最低位有几个连续的0
                                                                        32
                                                                        32位
000000000000000000000000000(27位)100000(5位)
Integer.numberOfLeadingZeros()31 - Integer.numberOfLeadingZeros()

    @Testpublic void printObjectArrayScale() throws NoSuchFieldException, IllegalAccessException {Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");theUnsafeInstance.setAccessible(true);Unsafe U = (Unsafe) theUnsafeInstance.get(Unsafe.class);Class<?> objectArr = Object[].class;Class<?> intArr = int[].class;Class<?> longArr = long[].class;Class<?> byteArr = byte[].class;int objectScale = U.arrayIndexScale(objectArr);int intScale = U.arrayIndexScale(intArr);int longScale = U.arrayIndexScale(longArr);int byteScale = U.arrayIndexScale(byteArr);System.out.println("Object[]的sacle=" + objectScale);System.out.println("int[]的sacle=" + intScale);System.out.println("long[]的sacle=" + longScale);System.out.println("byte[]的sacle=" + byteScale);
}

可以通过上面的方法测试,引用类型的数组的scale是4,因为虽然不同对象占用内存大小不一,但是对象数组每个元素是指向对应对象的引用,即内存地址

常规的想法是通过 scale * index 来计算某个元素相对于起始位置的偏移量

    @Testpublic void findArrayByBaseAndScale() throws NoSuchFieldException, IllegalAccessException {Class<Unsafe> clazz = Unsafe.class;Field unsafeField = clazz.getDeclaredField("theUnsafe");unsafeField.setAccessible(true);Unsafe unsafe = (Unsafe)unsafeField.get(null);int[] temp = {1, 2, 3 , 4};int base = unsafe.arrayBaseOffset(int[].class);int scale = unsafe.arrayIndexScale(int[].class);System.out.println(unsafe.getInt(temp , base + 0 * scale));System.out.println(unsafe.getInt(temp , base + 1 * scale));System.out.println(unsafe.getInt(temp , base + 2 * scale));System.out.println(unsafe.getInt(temp , base + 3 * scale));
}

 可以看到顺利取到了数组元素

这里看看CurrentHashMap是怎么计算元素的偏移量的

    @SuppressWarnings("unchecked")static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);}

这里测试一下它的这种方法

    @Testpublic void findArrayByBaseAndScale1() throws NoSuchFieldException, IllegalAccessException {Class<Unsafe> clazz = Unsafe.class;Field unsafeField = clazz.getDeclaredField("theUnsafe");unsafeField.setAccessible(true);Unsafe unsafe = (Unsafe)unsafeField.get(null);int[] temp = {1, 2, 3 , 4};int base = unsafe.arrayBaseOffset(int[].class);int scale = unsafe.arrayIndexScale(int[].class);int ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);System.out.println("第一个元素:" + unsafe.getInt(temp , base + (0 << ASHIFT) ));System.out.println("第二个元素:" + unsafe.getInt(temp , base + (1 << ASHIFT) ));System.out.println("第三个元素:" + unsafe.getInt(temp , base + (2 << ASHIFT) ));System.out.println("第四个元素:" + unsafe.getInt(temp , base + (3 << ASHIFT) ));}

 可以看到也顺利取到了数组的元素

熟悉位运算的很容易理解,其实这就是利用了一个位运算的技巧,通过向左移来实现扩大为2的n次方倍,而scale正好是2的n次方,所以可以这样计算

http://www.hkea.cn/news/333910/

相关文章:

  • 怎么把自己笔记本做服务器做个网站搭建网站基本步骤
  • jeecms做企业网站成都网站建设公司排名
  • 沈阳招聘网站开发地推项目平台
  • 798艺术区成都seo达人
  • 平度网站建设抖音代运营收费详细价格
  • 株洲网站优化找哪家seo优化的价格
  • 找印度人做网站sem竞价推广公司
  • 山西网站推广公司网站关键词优化怎么弄
  • 微信分销是什么重庆优化seo
  • 武汉企业网站推广方案永久免费无代码开发平台网站
  • 网站开发岗位群怎样推广产品
  • 桐城市美丽乡村建设专题网站石家庄整站优化技术
  • 北京建网站的公司哪个比较好郑州seo价格
  • 进空间的网站网络营销常见的工具
  • wordpress发文章的id怎么不连续如何做好搜索引擎优化工作
  • 交互式网站如何做seo推广软件排名
  • 西部建设网站惠州seo排名优化
  • 做环球资源网站有没有效果2024百度下载
  • 织梦 安装网站网站搭建需要多少钱
  • 做网站购买备案域名性价比高seo的排名优化
  • 潍坊中脉网站建设公司淄博seo公司
  • 深圳做网站推广哪家好青岛关键词优化平台
  • 呼和浩特市网站建设公司uc搜索引擎入口
  • 网站怎么做关键词搜索电子商务主要学什么内容
  • python做的网站漏洞百度竞价推广开户联系方式
  • 做任务换流量的网站怎么自己制作网页
  • 福清建设局网站火蝠电商代运营公司
  • 爱玖货源站在线智能识图
  • 上海网络营销软件windows优化大师win10
  • 专做美妆的视频网站ui设计