精华内容
下载资源
问答
  • DDR3 内存条原理

    热门讨论 2012-03-04 15:58:42
    这是DDR3内存条详细的pdf原理图资料,是UDIMM(无缓冲双通道内存模块),240个引脚。
  • DDR4台式机内存条原理图,用于内存条维修的第一手好资料
  • 内存的物理结构和工作原理

    千次阅读 2014-04-22 17:06:42
    内存的物理结构和工作原理 作者:xiaofeng 来源:PConline 发布时间:2012-11-01 点击数:1163  内存也叫主存,是PC系统存放数据与指令的半导体存储器单元,也叫主存储器(Main Memory),通常分为只读...

    内存的物理结构和工作原理

    作者:xiaofeng 来源:PConline 发布时间:2012-11-01 点击数:1163

      内存也叫主存,是PC系统存放数据与指令的半导体存储器单元,也叫主存储器(Main Memory),通常分为只读存储器(ROM-Read Only Memory)、随机存储器(RAM-Red Access Memory)和高速缓存存储器(Cache)。我们平常所指的内存条其实就是RAM,其主要的作用是存放各种输入、输出数据和中间计算结果,以及与外部存储器交换信息时做缓冲之用。

    结构

    1、PCB板

      内存条的PCB板多数都是绿色的。如今的电路板设计都很精密,所以都采用了多层设计,例如4层或6层等,所以PCB板实际上是分层的,其内部也有金属的布线。理论上6层PCB板比4层PCB板的电气性能要好,性能也较稳定,所以名牌内存多采用6层PCB板制造。因为PCB板制造严密,所以从肉眼上较难分辩PCB板是4层或6层,只能借助一些印在PCB板上的符号或标识来断定。

    2、金手指

      黄色的接触点是内存与主板内存槽接触的部分,数据就是靠它们来传输的,通常称为金手指。金手指是铜质导线,使用时间长就可能有氧化的现象,会影响内存的正常工作,易发生无法开机的故障,所以可以隔一年左右时间用橡皮擦清理一下金手指上的氧化物。 

    3、内存芯片

      内存的芯片就是内存的灵魂所在,内存的性能、速度、容量都是由内存芯片组成的。

    4、内存颗粒空位

           在内存条上你可能常看到这样的空位,这是因为采用的封装模式预留了一片内存芯片为其他采用这种封装模式的内存条使用。这块内存条就是使用9片装PCB,预留ECC校验模块位置。

    5、电容

      PCB板上必不可少的电子元件就是电容和电阻了,这是为了提高电气性能的需要。电容采用贴片式电容,因为内存条的体积较小,不可能使用直立式电容,但这种贴片式电容性能一点不差,它为提高内存条的稳定性起了很大作用。

    6、电阻

      电阻也是采用贴片式设计,一般好的内存条电阻的分布规划也很整齐合理。

    7、内存固定卡缺口

      内存插到主板上后,主板上的内存插槽会有两个夹子牢固的扣住内存,这个缺口便是用于固定内存用的。

    8、内存脚缺口

           内存的脚上的缺口一是用来防止内存插反的(只有一侧有),二是用来区分不同的内存,以前的SDRAM内存条是有两个缺口的,而DDR则只有一个缺口,不能混插。

    9、SPD

      SPD是一个八脚的小芯片,它实际上是一个EEPROM可擦写存贮器,这的容量有256字节,可以写入一点信息,这信息中就可以包括内存的标准工作状态、速度、响应时间等,以协调计算机系统更好的工作。从PC100时代开始,PC100规准中就规定符合PC100标准的内存条必须安装SPD,而且主板也可以从SPD中读取到内存的信息,并按SPD的规定来使内存获得最佳的工作环境。

    内存工作原理

    1、内存寻址

           首先,内存从CPU获得查找某个数据的指令,然后再找出存取资料的位置时(这个动作称为“寻址”),它先定出横坐标(也就是“列地址”)再定出纵坐标(也就是“行地址”),这就好像在地图上画个十字标记一样,非常准确地定出这个地方。对于电脑系统而言,找出这个地方时还必须确定是否位置正确,因此电脑还必须判读该地址的信号,横坐标有横坐标的信号(也就是RAS信号,Row Address Strobe)纵坐标有纵坐标的信号(也就是CAS信号,Column Address Strobe),最后再进行读或写的动作。

    2、内存传输

      为了储存资料,或者是从内存内部读取资料,CPU都会为这些读取或写入的资料编上地址(也就是我们所说的十字寻址方式),这个时候,CPU会通过地址总线(Address Bus)将地址送到内存,然后数据总线(Data Bus)就会把对应的正确数据送往微处理器,传回去给CPU使用。

    3、存取时间

      存取时间,指的是CPU读或写内存内资料的过程时间,也称为总线循环(bus cycle)。以读取为例,从CPU发出指令给内存时,便会要求内存取用特定地址的特定资料,内存响应CPU后便会将CPU所需要的资料送给CPU,一直到CPU收到数据为止,便成为一个读取的流程。因此,这整个过程简单地说便是CPU给出读取指令,内存回复指令,并丢出资料给CPU的过程。我们常说的6ns(纳秒,秒-9)就是指上述的过程所花费的时间,而ns便是计算运算过程的时间单位。我们平时习惯用存取时间的倒数来表示速度,比如6ns的内存实际频率为1/6ns=166MHz(如果是DDR就标DDR333,DDR2就标DDR2 667)。

    4、内存延迟

      内存的延迟时间(也就是所谓的潜伏期,从FSB到DRAM)等于下列时间的综合:FSB同主板芯片组之间的延迟时间(±1个时钟周期),芯片组同DRAM之间的延迟时间(±1个时钟周期),RAS到CAS延迟时间:RAS(2-3个时钟周期,用于决定正确的行地址),CAS延迟时间 (2-3时钟周期,用于决定正确的列地址),另外还需要1个时钟周期来传送数据,数据从DRAM输出缓存通过芯片组到CPU的延迟时间(±2个时钟周期)。一般的说明内存延迟涉及四个参数CAS(Column Address Strobe 行地址控制器)延迟,RAS(Row Address Strobe列地址控制器)-to-CAS延迟,RAS Precharge(RAS预冲电压)延迟,Act-to-Precharge(相对于时钟下沿的数据读取时间)延迟。其中CAS延迟比较重要,它反映了内存从接受指令到完成传输结果的过程中的延迟。大家平时见到的数据3—3—3—6中,第一参数就是CAS延迟(CL=3)。当然,延迟越小速度越快。

    展开全文
  • 机械硬盘的存储结构及原理

    千次阅读 2019-01-25 16:12:02
    硬盘是电脑主要的存储媒介之一。根据硬盘的读写方式和存储方式不同,当前主流的硬盘可以分为固态硬盘(SSD硬盘)...故而本博客主要对机械硬盘的结构原理进行讲解。 硬盘是由很多的盘片组成,而其存储信息的方式...

    硬盘是电脑主要的存储媒介之一。根据硬盘的读写方式和存储方式不同,当前主流的硬盘可以分为固态硬盘(SSD硬盘)、机械硬盘(HDD 硬盘)两种。由于固态硬盘存在价格昂贵、容量较小和一旦损坏难以修复等特点,当前市场主要流行的依然是机械硬盘。当然,在高端计算机中通常会结合两种硬盘来获取更好的性能,这里暂且不提。故而本博客主要对机械硬盘的结构和原理进行讲解。

    硬盘是由很多的盘片组成,而其存储信息的方式就是通过盘片表面的磁性物质来存储数据。把盘片放在显微镜下放大,可以看到盘片表面是凹凸不平的,凸起的地方被磁化,代表数字 1,凹的地方没有被磁化,代表数字 0,因此硬盘可以通过二进制的形式来存储表示文字、图片等的信息。

    机械硬盘主要由磁盘、磁头、盘片主轴、控制电机、磁头控制器、数据转换器、接口、缓存等几个部分组成。

    所有的盘片都固定在一个旋转轴上,这个轴即盘片主轴。所有的盘片之间是绝对平行的,且在每个盘片的盘面上都有一个磁头来对磁盘上的数据进行读写操作。所有的磁头连在一个磁头控制器上,由磁头控制器负责各个磁头的运动,磁头可沿盘片的半径方向移动,实际上磁头是围绕固定点做圆周移动(如果有兴趣可以通过上面的磁盘结构图自己看,这里不加以解释),而且传统的硬盘中由于所有磁头都固定在同一个控制器上,所以每个磁头同一时刻是同轴的,即从正上方往下看,所有磁头任何时候都是重叠的,在这种情况下每一时刻只有一个磁头能够进行数据的读取。当硬盘启动时盘片在主轴的带动下以每分钟数千转到上万转的速度在高速运转,而磁头在控制器的控制下固定在某个位置上对经过其下方的磁盘区域进行信息的读写。

    由前面的描述可知,硬盘的数据主要存储在许多盘片上的磁性物质上,而这些这些信息是通过磁头在某一点上对其下方的转动的磁片进行写入的,故而这些信息以一条条围绕主轴的同心圆细线的形式存在。为了方便描述与管理,我们把这些存储信息的同心圆细线称为磁道,将盘片中用于记录信息的面称为盘面(当前主流的硬盘一般每个盘片的两个面都会用于记录信息,所以每个盘片对应两个盘面。当然,也有部分只有一面用于记录信息的,在此暂不赘述),而多个盘片上半径相同的磁道称为柱面,为了更好的对磁盘资源进行过滤,我们有将每个磁道划分为均匀的几段称为扇区。

    下面对几个名词的定义是作用进行解析:

    盘面:硬盘的盘片一般用铝合金材料做基片,硬盘的每一个盘片的两个面都可以用于记录信息,一般每个盘面都会得到利用,都可以存储数据,成为盘面。当然,也有的硬盘为了简化磁头结构或其他原因只利用其中一个面来记录信息,这样每个盘片就只对应一个盘面。每一个盘面都有一个盘面号,按顺序从上至下从 0 开始编号。在硬盘系统中,盘面号又叫磁头号,因为每一个盘面都有一个对应的读写磁头。

    磁道:磁盘在格式化时被划分成许多用于记录信息的同心圆,这些同心圆轨迹叫做磁道。磁道从外向内从 0 开始顺序编号,硬盘的每一个盘面有 300-1024 个磁道,新式大容量硬盘每面的磁道数更多,信息以脉冲串的形式记录在这些轨迹中,这些同心圆不是连续记录数据,而是被划分成一段段的圆弧。这些圆弧的角速度一样,由于径向长度不一样,所以线速度也不一样,外圈的线速度较内圈的线速度大,所以同样的转速度下,外圈在同样时间段里,划过的圆弧长度要比内圈划过的圆弧长度大。磁道是看不见的,只是盘面上以特殊形式磁化了的一些磁化区,在磁盘格式化时就已规划完毕。

    柱面:所有盘面上半径相同的磁道构成的一个圆柱面,即在磁盘上所有与主轴距离相同的磁道成为柱面。之所以给出柱面这一概念主要是为了提高磁盘的读写速率。在机械硬盘中数据的读取是依靠磁头来进行的,每个盘面对应一个磁头,而这些磁头通常被固定在同一转轴上,同时这些磁头从磁盘的上方看是重合的,也就是说所有磁头同一时间处于同一半径的磁道上。而由哪个磁头进行数据的读取则由对应的控制系统来进行电子切换,这个过程相对于将磁头移动的相邻的磁道是一个极快的过程,为了提高数据的读/写速率,数据的存储一般是按照柱面的顺序来的,具体的做法就是数据先存储在某一柱面的第一个磁道上,之后建数据存储到同一柱面的第二个磁道上,一直到同一柱面的所有磁道都使用完后才转到下一柱面进行读/写操作。

    扇区:扇区是磁盘读写的基本单位,每个扇区包括 512 个字节的数据和一些其他信息,这些信息包含存储数据地址的标识符(盘面号,柱面号,扇区号等)和用于保护数据的纠错码(ECC)。在传统磁盘上,一般盘面上每一个磁道所对应的扇区是相同的,由于盘面上的磁道大小是不均匀的,其中越靠近主轴的磁道长度越小,越远离主轴的磁道长度越大,所以这样的分配方式会造成“大面积小数据”的浪费情况,为了避免这种情况很多硬盘采用同密度盘片,所以半径不同的磁道划分成出来的扇区数量也是不同的,磁道越长所包含的扇区也也就也多。关于扇区号,目前主要有两种定义规则,其中一种是每个磁道拥有自己的扇区号,在每个磁道中扇区号都是从0开始增加的,之后通过CHS(也称3D)寻址方式来对对应扇区进行访问,而另一种则是对硬盘上所有的扇区进行统一编号,其编号规则为:LBA(逻辑扇区号)=磁头数 × 每磁道扇区数 × 当前所在柱面号 + 每磁道扇区数 × 当前所在磁头号 + 当前所在扇区号 – 1 。这两种方式中,前者适合对每个磁道所拥有的磁道相同的传统磁盘,而后者时候采用同密度盘片的磁盘。

    展开全文
  • Java 内存模型GC原理

    万次阅读 多人点赞 2011-03-16 09:58:00
    一个优秀Java程序员,必须了解Java内存模型、GC工作原理,以及如何优化GC的性能、与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统、实时系统等,只有全面提升内存的管理效率,才能提高整个应用...

    一个优秀Java程序员,必须了解Java内存模型、GC工作原理,以及如何优化GC的性能、与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统、实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能。

    本文将从JVM内存模型、GC工作原理,以及GC的几个关键问题进行探讨,从GC角度提高Java程序的性能。


    一、Java内存模型

    按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。

    JVM主要管理两种类型内存:堆和非堆,堆内存(Heap Memory)是在 Java 虚拟机启动时创建,非堆内存(Non-heap Memory)是在JVM堆之外的内存。

    简单来说,堆是Java代码可及的内存,留给开发人员使用的;非堆是JVM留给自己用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。

    JVM 内存包含如下几个部分:

    • 堆内存(Heap Memory): 存放Java对象
    • 非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data
    • 其它(Other): 存放JVM 自身代码等


    在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部分内存并不一定都会被JVM使用,但是可以确定的是这部分保留的内存不会被其他进程使用,这部分内存大小由-Xmx 参数指定。而另一部分内存在JVM启动时就分配给JVM,作为JVM的初始Heap内存使用,这部分内存是由 -Xms 参数指定。


    详细配置文件目录:eclipse/eclipse.ini

    默认空余堆内存小于40%时,JVM 就会增大堆直到-Xmx 的最大限制,可以由 -XX:MinHeapFreeRatio 指定。 

    默认空余堆内存大于70%时,JVM 会减少堆直到-Xms的最小限制,可以由  -XX:MaxHeapFreeRatio   指定,详见

    可以通过 -XX:MaxPermSize 设置Non-Heap大小,详细参见我的百度博客


    二、Java内存分配

    Java的内存管理实际上就是变量对象的管理,其中包括对象的分配和释放。

    JVM内存申请过程如下:

    1. JVM 会试图为相关Java对象在Eden中初始化一块内存区域
    2. 当Eden空间足够时,内存申请结束;否则到下一步
    3. JVM 试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区
    4. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
    5. 当OLD区空间不够时,JVM 会在OLD区进行完全的垃圾收集(0级)
    6. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory”错误


    三、GC基本原理

    GC(Garbage Collection),是JAVA/.NET中的垃圾收集器。

    Java是由C++发展来的,它摈弃了C++中一些繁琐容易出错的东西,引入了计数器的概念,其中有一条就是这个GC机制(C#借鉴了JAVA)

    编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。所以,Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。

    对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间。

    对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的".当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。但是,为了保证 GC能够在不同平台实现的问题,Java规范对GC的很多行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定。因此,不同的JVM的实现者往往有不同的实现算法。这也给Java程序员的开发带来行多不确定性。本文研究了几个与GC工作相关的问题,努力减少这种不确定性给Java程序带来的负面影响。


    四、GC分代划分

    JVM内存模型中Heap区分两大块,一块是 Young Generation,另一块是Old Generation


    1) 在Young Generation中,有一个叫Eden Space的空间,主要是用来存放新生的对象,还有两个Survivor Spaces(from、to),它们的大小总是一样,它们用来存放每次垃圾回收后存活下来的对象。

    2) 在Old Generation中,主要存放应用程序中生命周期长的内存对象。

    3) 在Young Generation块中,垃圾回收一般用Copying的算法,速度快。每次GC的时候,存活下来的对象首先由Eden拷贝到某个SurvivorSpace当Survivor Space空间满了后剩下的live对象就被直接拷贝到OldGeneration中去。因此,每次GC后,Eden内存块会被清空。

    4) 在Old Generation块中,垃圾回收一般用mark-compact的算法,速度慢些,但减少内存要求。

    5) 垃圾回收分多级,0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收Young中的垃圾,内存溢出通常发生于OLD段或Perm段垃圾回收后,仍然无内存空间容纳新的Java对象的情况。


    五、增量式GC

    增量式GC(Incremental GC),是GC在JVM中通常是由一个或一组进程来实现的,它本身也和用户程序一样占用heap空间,运行时也占用CPU。

    当GC进程运行时,应用程序停止运行。因此,当GC运行时间较长时,用户能够感到Java程序的停顿,另外一方面,如果GC运行时间太短,则可能对象回收率太低,这意味着还有很多应该回收的对象没有被回收,仍然占用大量内存。因此,在设计GC的时候,就必须在停顿时间和回收率之间进行权衡。一个好的GC实现允许用户定义自己所需要的设置,例如有些内存有限的设备,对内存的使用量非常敏感,希望GC能够准确的回收内存,它并不在意程序速度的快慢。另外一些实时网络游戏,就不能够允许程序有长时间的中断。

    增量式GC就是通过一定的回收算法,把一个长时间的中断,划分为很多个小的中断,通过这种方式减少GC对用户程序的影响。虽然,增量式GC在整体性能上可能不如普通GC的效率高,但是它能够减少程序的最长停顿时间。

    Sun JDK提供的HotSpot JVM就能支持增量式GC。HotSpot JVM缺省GC方式为不使用增量GC,为了启动增量GC,我们必须在运行Java程序时增加-Xincgc的参数。

    HotSpot JVM增量式GC的实现是采用Train GC算法,它的基本想法就是:将堆中的所有对象按照创建和使用情况进行分组(分层),将使用频繁高和具有相关性的对象放在一队中,随着程序的运行,不断对组进行调整。当GC运行时,它总是先回收最老的(最近很少访问的)的对象,如果整组都为可回收对象,GC将整组回收。这样,每次GC运行只回收一定比例的不可达对象,保证程序的顺畅运行。


    六、详解函数finalize

    finalize 是位于Object类的一个方法,详见我的开源项目:src-jdk1.7.0_02

    protected void finalize() throws Throwable { }

    该方法的访问修饰符为protected,由于所有类为Object的子类,因此用户类很容易访问到这个方法。

    由于,finalize函数没有自动实现链式调用,我们必须手动的实现,因此finalize函数的最后一个语句通常是 super.finalize()。通过这种方式,我们可以实现从下到上实现finalize的调用,即先释放自己的资源,然后再释放父类的资源。根据Java语言规范,JVM保证调用finalize函数之前,这个对象是不可达的,但是JVM不保证这个函数一定会被调用。另外,规范还保证finalize函数最多运行一次。

    很多Java初学者会认为这个方法类似与C++中的析构函数,将很多对象、资源的释放都放在这一函数里面。其实,这不是一种很好的方式,原因有三:

    其一GC为了能够支持finalize函数,要对覆盖这个函数的对象作很多附加的工作。

    其二、在finalize运行完成之后,该对象可能变成可达的,GC还要再检查一次该对象是否是可达的。因此,使用 finalize会降低GC的运行性能。

    其三由于GC调用finalize的时间是不确定的,因此通过这种方式释放资源也是不确定的。


    通常,finalize用于一些不容易控制、并且非常重要资源的释放,例如一些I/O的操作,数据的连接。这些资源的释放对整个应用程序是非常关键的。在这种情况下,程序员应该以通过程序本身管理(包括释放)这些资源为主,以finalize函数释放资源方式为辅,形成一种双保险的管理机制,而不应该仅仅依靠finalize来释放资源。

    下面给出一个例子说明,finalize函数被调用以后,仍然可能是可达的,同时也可说明一个对象的finalize只可能运行一次。

    	class MyObject {
    		Test main; 		// 记录Test对象,在finalize中时用于恢复可达性
    
    		public MyObject(Test t) {
    			main = t; 	// 保存Test 对象
    		}
    
    		protected void finalize() {
    			main.ref = this;	// 恢复本对象,让本对象可达
    			System.out.println("This is finalize");		// 用于测试finalize只运行一次
    		}
    	}
    
    	class Test {
    		MyObject ref;
    
    		public static void main(String[] args) {
    			Test test = new Test();
    			test.ref = new MyObject(test);
    			test.ref = null; 	// MyObject对象为不可达对象,finalize将被调用
    			System.gc();
    			if (test.ref != null)
    				System.out.println("My Object还活着");
    		}
    	}

    运行结果:

      This is finalize

      My Object还活着

    此例子中需要注意,虽然MyObject对象在finalize中变成可达对象,但是下次回收时候,finalize却不再被调用,因为finalize函数最多只调用一次。


    七、GC程序交互

    程序如何与GC进行交互呢? Java2增强了内存管理功能,增加了一个java.lang.ref包,详见我的开源项目:src-jdk1.7.0_02

    其中定义了三种引用类。这三种引用类分别为:SoftReference、 WeakReference、 PhantomReference

    通过使用这些引用类,程序员可以在一定程度与GC进行交互,以便改善GC的工作效率,这些引用类的引用强度介于可达对象和不可达对象之间。

    创建一个引用对象也非常容易,例如:如果你需要创建一个Soft Reference对象,那么首先创建一个对象,并采用普通引用方式(可达对象);然后再创建一个SoftReference引用该对象;最后将普通引用设置为null。通过这种方式,这个对象就只有一个Soft Reference引用。同时,我们称这个对象为Soft Reference 对象。

    Soft Reference的主要特点是据有较强的引用功能。只有当内存不够的时候,才进行回收这类内存,因此在内存足够的时候,它们通常不被回收。另外,这些引用对象还能保证在Java抛出OutOfMemory 异常之前,被设置为null。它可以用于实现一些常用图片的缓存,实现Cache的功能,保证最大限度的使用内存而不引起OutOfMemory。以下给出这种引用类型的使用伪代码:

    		// 申请一个图像对象
    	  Image image=new Image();		// 创建Image对象
    	  …
    	  // 使用 image
    	  …
    	  // 使用完了image,将它设置为soft 引用类型,并且释放强引用;
    	  SoftReference sr=new SoftReference(image);
    	  image=null;
    	  …
    	  // 下次使用时
    	  if (sr!=null) 
    			image=sr.get();
    	  else{
    	  		image=new Image();	//由于GC由于低内存,已释放image,因此需要重新装载;
    	  		sr=new SoftReference(image);
    	  }

    Weak引用对象与Soft引用对象的最大不同就在于:GC在进行回收时,需要通过算法检查是否回收Soft引用对象,而对于Weak引用对象,GC总是进行回收。Weak引用对象更容易、更快被GC回收。虽然,GC在运行时一定回收Weak对象,但是复杂关系的Weak对象群常常需要好几次GC的运行才能完成。Weak引用对象常常用于Map结构中,引用数据量较大的对象,一旦该对象的强引用为null时,GC能够快速地回收该对象空间。

    Phantom引用的用途较少,主要用于辅助finalize函数的使用。Phantom对象指一些对象,它们执行完了finalize函数,并为不可达对象,但是它们还没有被GC回收。这种对象可以辅助finalize进行一些后期的回收工作,我们通过覆盖Reference的clear()方法,增强资源回收机制的灵活性。


    八、Java编程建议

    根据GC的工作原理,我们可以通过一些技巧和方式,让GC运行更加有效率,更加符合应用程序的要求。一些关于程序设计的几点建议:

    1)最基本的建议就是尽早释放无用对象的引用。大多数程序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后,自动设置为 null.我们在使用这种方式时候,必须特别注意一些复杂的对象图,例如数组,队列,树,图等,这些对象之间有相互引用关系较为复杂。对于这类对象,GC 回收它们一般效率较低。如果程序允许,尽早将不用的引用对象赋为null,这样可以加速GC的工作。

    2)尽量少用finalize函数。finalize函数是Java提供给程序员一个释放对象或资源的机会。但是,它会加大GC的工作量,因此尽量少采用finalize方式回收资源。

    3)如果需要使用经常使用的图片,可以使用soft应用类型。它可以尽可能将图片保存在内存中,供程序调用,而不引起OutOfMemory.

    4)注意集合数据类型,包括数组,树,图,链表等数据结构,这些数据结构对GC来说,回收更为复杂。另外,注意一些全局的变量,以及一些静态变量。这些变量往往容易引起悬挂对象(dangling reference),造成内存浪费。

    5)当程序有一定的等待时间,程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。使用增量式GC可以缩短Java程序的暂停时间。




    参考推荐:

    Java内存模型及GC原理

    一个优秀的Java程序员必须了解的GC机制

    Android 智能指针原理推荐


    Java虚拟机规范

    Java虚拟机参数

    Java内存模型

    Java系列教程推荐

    Java垃圾回收原理(360doc)


    Java内存模型及GC原理(图解)

    Java的内存结构和垃圾收集(图解)

    JDK5.0中JVM堆模型、GC垃圾收集详细解析(图解)


    Java内存泄露的理解与解决

    Java gc的调用机制和编程规则

    Java 内存泄漏实例及解决方案研究


    JVM 优点与缺点的深入分析 [草稿]


    展开全文
  • RoaringBitmap数据结构及原理

    万次阅读 多人点赞 2017-10-25 15:56:14
    BitmapContainer是一横线,始终占用8kb RunContainer比较奇葩,因为和数据的连续性关系太大,因此只能画出一个上下限范围。不管数据量多少,下限始终是4字节;上限在最极端的情况下可以达到128kb。 ...

    首先

    RoaringBitmap数据结构

    每个RoaringBitmap(GitHub链接)中都包含一个RoaringArray,名字叫highLowContainer
    highLowContainer存储了RoaringBitmap中的全部数据。

    RoaringArray highLowContainer;

    这个名字意味着,会将32位的整形(int)拆分成高16位和低16位两部分(两个short)来处理。

    RoaringArray的数据结构很简单,核心为以下三个成员:

    short[] keys;
    Container[] values;
    int size;

    每个32位的整形,高16位会被作为key存储到short[] keys中,低16位则被看做value,存储到Container[] values中的某个Container中。keysvalues通过下标一一对应。size则标示了当前包含的key-value pair的数量,即keysvalues中有效数据的数量。

    keys数组永远保持有序,方便二分查找。

    三种Container

    下面介绍到的是RoaringBitmap的核心,三种Container。

    通过上面的介绍我们知道,每个32位整形的高16位已经作为key存储在RoaringArray中了,那么Container只需要处理低16位的数据。

    ArrayContainer

    static final int DEFAULT_MAX_SIZE = 4096
    
    short[] content;

    结构很简单,只有一个short[] content,将16位value直接存储。

    short[] content始终保持有序,方便使用二分查找,且不会存储重复数值。

    因为这种Container存储数据没有任何压缩,因此只适合存储少量数据。

    ArrayContainer占用的空间大小与存储的数据量为线性关系,每个short为2字节,因此存储了N个数据的ArrayContainer占用空间大致为2N字节。存储一个数据占用2字节,存储4096个数据占用8kb。

    根据源码可以看出,常量DEFAULT_MAX_SIZE值为4096,当容量超过这个值的时候会将当前Container替换为BitmapContainer。

    BitmapContainer

    final long[] bitmap;

    这种Container使用long[]存储位图数据。我们知道,每个Container处理16位整形的数据,也就是0~65535,因此根据位图的原理,需要65536个比特来存储数据,每个比特位用1来表示有,0来表示无。每个long有64位,因此需要1024个long来提供65536个比特。

    因此,每个BitmapContainer在构建时就会初始化长度为1024的long[]。这就意味着,不管一个BitmapContainer中只存储了1个数据还是存储了65536个数据,占用的空间都是同样的8kb。

    RunContainer

    private short[] valueslength;
    
    int nbrruns = 0;

    RunContainer中的Run指的是行程长度压缩算法(Run Length Encoding),对连续数据有比较好的压缩效果。

    它的原理是,对于连续出现的数字,只记录初始数字和后续数量。即:

    • 对于数列11,它会压缩为11,0
    • 对于数列11,12,13,14,15,它会压缩为11,4
    • 对于数列11,12,13,14,15,21,22,它会压缩为11,4,21,1

    源码中的short[] valueslength中存储的就是压缩后的数据。

    这种压缩算法的性能和数据的连续性(紧凑性)关系极为密切,对于连续的100个short,它能从200字节压缩为4字节,但对于完全不连续的100个short,编码完之后反而会从200字节变为400字节。

    如果要分析RunContainer的容量,我们可以做下面两种极端的假设:

    • 最好情况,即只存在一个数据或只存在一串连续数字,那么只会存储2个short,占用4字节
    • 最坏情况,0~65535的范围内填充所有的奇数位(或所有偶数位),需要存储65536个short,128kb

    Container性能总结

    读取时间

    只有BitmapContainer可根据下标直接寻址,复杂度为O(1),ArrayContainer和RunContainer都需要二分查找,复杂度O(log n)

    内存占用

    Container内存比较

    这是我画的一张图,大致描绘了各Container占用空间随数据量的趋势。

    其中,

    • ArrayContainer一直线性增长,在达到4096后就完全比不上BitmapContainer了
    • BitmapContainer是一条横线,始终占用8kb
    • RunContainer比较奇葩,因为和数据的连续性关系太大,因此只能画出一个上下限范围。不管数据量多少,下限始终是4字节;上限在最极端的情况下可以达到128kb。

    RoaringBitmap针对Container的优化策略

    创建时:

    • 创建包含单个值的Container时,选用ArrayContainer
    • 创建包含一串连续值的Container时,比较ArrayContainer和RunContainer,选取空间占用较少的

    转换:

    针对ArrayContainer:

    • 如果插入值后容量超过4096,则自动转换为BitmapContainer。因此正常使用的情况下不会出现容量超过4096的ArrayContainer
    • 调用runOptimize()方法时,会比较和RunContainer的空间占用大小,选择是否转换为RunContainer。

    针对BitmapContainer:

    • 如果删除某值后容量低至4096,则会自动转换为ArrayContainer。因此正常使用的情况下不会出现容量小于4096的BitmapContainer
    • 调用runOptimize()方法时,会比较和RunContainer的空间占用大小,选择是否转换为RunContainer。

    针对RunContainer:

    • 只有在调用runOptimize()方法才会发生转换,会分别和ArrayContainer、BitmapContainer比较空间占用大小,然后选择是否转换。

    以上

    展开全文
  • EXE文件结构及原理

    千次阅读 2013-11-19 19:53:56
    EXE文件结构及原理 转自:http://blog.163.com/ma_youzhong/blog/static/42459154200831835636136/ EXE文件分为两个部分: EXE头部(包括一些标识信息和重定位表)和程序本体(程序本身). EXE头部的大小由EXE文件...
  • .COM文件结构及原理

    千次阅读 2012-12-24 20:48:01
    .COM文件结构及原理  com文件结构比较简单,它包含程序的一个绝对映像,即为了运行程序准确的处理器指令和内存中的数据,MS-DOS通过直接把该映像从文件直接复制到内存,从而加载com程序,而不做任何改变。  ...
  • com文件结构及原理

    千次阅读 2007-02-01 17:19:00
    com文件结构及原理 作者:不详 文章来源:来自 Internet 点击数: 0 更新时间:2003-11-12
  • Mysql数据结构及算法原理

    万次阅读 2018-04-06 21:01:42
    目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构,在本文的下一节会结合存储器原理及计算机存取原理讨论为什么B-Tree和B+Tree在被如此广泛用于索引,这一节先单纯从数据结构角度描述它们。...
  • 文章目录一、冯诺依曼简介二、冯诺依曼计算机的工作原理1、存储程序(存储系统构建与快速访问)2、程序控制(指令系统、控制器设计等)三、冯诺依曼计算机的组成(硬件+软件)1、硬件系统运算器控制器存储器输入/...
  • DRAM内存原理(二)结构和功能

    万次阅读 2014-12-08 09:03:22
    内存最基本的单位是内存“细胞”——也就是我们前面展示给大家DRAM基本单元示意图所示的部分,下面我们对这个部分通称为DRAM基本单元。每个DRAM基本单元代表一个“位”——Bit(也就是一个比特),并且有一个由列...
  • JVM结构及各个组件原理

    千次阅读 2019-03-28 11:21:04
    JVM结构及各个组件原理 类装载器ClassLoader 负责加载class文件,class文件在文件开头有特定的文件标示,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader只负责...
  • 内存与cpu工作原理

    千次阅读 2017-05-03 22:25:47
    内存:通电状态下进行数据存储   cpu内部大致结构 程序控制器(CPU的控制中心) 职责: 1 分析或解释 指令 2 根据或析与解释结果向其他组件发出命令 3 控制cpu的工作进度和工作方式   当一指令进入...
  • MySQL索引背后的数据结构及算法原理

    千次阅读 多人点赞 2018-03-20 20:45:22
     在编程领域有一句人尽皆知的法则“程序 = 数据结构 + 算法”,我个人是不太赞同这句话(因为我觉得程序不仅仅是数据结构加算法),但是在日常的学习和工作中我确认深深感受到数据结构和算法的重要性,很多东西,...
  • 深入理解JVM的内存结构及GC机制

    万次阅读 多人点赞 2017-11-23 02:12:38
    一、前言 JAVA GC(Garbage Collection,垃圾回收)机制是区别C++的一个重要特征,C++需要开发者自己...但这并不意味着我们不用去理解GC机制的原理,因为如果不了解其原理,可能会引发内存泄漏、频繁GC导致应用卡顿
  • MySQL索引原理及BTree(B-/+Tree)结构详解

    万次阅读 多人点赞 2018-11-20 16:52:25
    数据结构及算法基础 索引的本质 B-Tree和B+Tree B-Tree B+Tree 带有顺序访问指针的B+Tree 为什么使用B-Tree(B+Tree) 主存存取原理 磁盘存取原理 局部性原理与磁盘预读 B-/+Tree索引的性能分析 MySQL...
  • JVM内存结构概述

    千次阅读 2019-08-20 23:32:58
    本节将会介绍一下JVM的内存结构,JVM运行时数据区的各个组成部分:堆,方法区,程序计数器,Java虚拟机栈,本地方法栈,还会对Java堆的分代划分做个简单的介绍。 目录 前言 JVM是什么 JVM内存结构概览 运行时...
  • 很早就对数据在内存中的结构和体积有深入了解的想法。平时写代码的过程中,对于这些完全处于一种感性的认识,对于代码中使用的数据结构和对象,尤其是处理大量数据的时候,总有种把控不住的感觉。趁周六日有时间的...
  • dpdk大页内存原理

    千次阅读 2019-08-16 23:56:26
    在分析dpdk大页内存的源码之前,有必要对linux内存管理的原理以及大页内存原理有个了解,缺少这些底层基础知识,分析dpdk大页内存的源码将举步维艰。这篇文章详细介绍下linux内存管理以及大页内存的方方面面,为...
  • volatile实现原理分析
  • 内存寻址原理

    万次阅读 2016-01-10 20:25:02
    今天绿盟科技的安全技术专家就讲讲这个内存寻址的原理,文章分为上下两篇《内存寻址原理内存寻址方式》。 随着信息化发展和数据处理能力需求的提高,对计算机硬件产品的性能和容量也提出了新的挑战,要求...
  • Presto内存调优及原理(基础篇)

    千次阅读 2018-07-15 07:30:00
    使用的是一种称为内存池(memory-pool)的机制来管理presto中任务presto本身的内存使用。 目标和设计思路可查看: https://github.com/prestodb/presto/issues/2624 当前presto已经实现了其设定的目标: 更容易的让...
  • jvm原理内存模型GC机制

    千次阅读 2017-07-06 14:21:47
    JVM方法区结构内存模型) 1.1 程序计数器 1.2 虚拟机栈(java栈) 1.3 本地方法栈 1.4 方法区 1.5 堆 1.5.1 堆内存与栈内存需要说明 总结 2.GC机制 2.1 引用计数法 2.2 可达性分析算法 2.3 一般回收...
  • MySQL索引原理及B-Tree / B+Tree结构详解

    万次阅读 2019-08-09 12:30:22
    MySQL索引原理及B-Tree / B+Tree结构详解 目录 摘要 数据结构及算法基础 索引的本质 B-Tree和B+Tree B-Tree B+Tree 带有顺序访问指针的B+Tree 为什么使用B-Tree(B+Tree) 主存存取原理 磁盘存取原理 ...
  • 硬盘内部硬件结构和工作原理详解

    万次阅读 多人点赞 2018-05-07 09:19:26
    硬盘的外部物理结构 一般硬盘正面贴有产品标签,主要包括厂家信息和产品信息,如商标、型号、序列号、生产日期、容量、参数和主从设置方法等。这些信息是正确使用硬盘的基本依据,下面将逐步介绍它们的含义。 硬盘...
  • Linux内存管理原理

    千次阅读 2018-02-22 23:04:24
    =============================硬件原理及分页管理===============================1.分页机制 分页机制是现代CPU实现内存寻址的一种机制(早期的intel芯片内存寻址实现机制有分段机制); 早期的CPU对内存的寻址是...
  • 内存工作原理

    千次阅读 2015-11-29 14:18:51
    现代的PC(包括NB)都是以存储器为核心的多总线结构,即CPU只通过存储总线与主存储器交换信息(先在Cache里找数据,如果找不到,再去主存找)。输入输出设备通过I/O总线直接与主存储器交换信息。在I/O设备和主存储器...
  • 【数据结构】ArrayList原理及实现学习总结

    万次阅读 多人点赞 2016-04-19 18:09:27
    ArrayList是一种线性数据结构,它的底层是用数组实现的,相当于动态数组。与Java中的数组相比,它的容量能动态增长。类似于C语言中的动态申请内存,动态增长内存。 当创建一个数组的时候,就必须确定它的大小,...
  • 1 数据结构及算法基础1.1 索引的本质 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。也就是说索引是数据结构 数据库查询是数据库的最主要功能之一。数据本身的组织结构不可能完全...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 217,086
精华内容 86,834
关键字:

内存条的结构及原理