精华内容
下载资源
问答
  • 详解JavaScript中选取元素所有方法

    千次阅读 2018-04-05 19:43:37
    DOM中选取文档元素方法...1.通过ID选取元素: document.getElementById() 任何元素都可以有一个id属性,在文档中该值必须唯一,所以该方法返回一个DOM对象。通过id获取元素是最简单最常用的选取元素方法。getE...
    DOM中选取文档元素的方法总共有5种:
    1.通过id值。
    2.通过name属性值。
    3.通过指定的标签名。
    4.通过class类。

    5.通过css选择器。


    下面我就这五种方法详细解释一下吧。

    1.通过ID选取元素:  document.getElementById()
        任何元素都可以有一个id属性,在文档中该值必须唯一,所以该方法返回一个DOM对象。通过id获取元素是最简单最常用的选取元素的方法。
    getElementById(id值)。注意这个方法是Document对象的方法。所以使用方法通常如下:
    var el = document.getElementById("id");


    2.通过name属性选取元素:  document.getElementsByName()

        多个元素可能有同样的名字,所以该方法返回NodeList对象。
    getElementsByName(name值)定义在HTMLDocument类中,而不是在Document类中,所以它只对HTML文档有用,对XML文档无用。
    在对form、img、iframe、applet、embed、object元素设置name属性时要注意一点,这些元素的属性值将自动成为window和Document对象的对应属性。所以如果通过name属性值查找以上几个特殊的元素可以像获取属性值一样操作,如:
    //针对<form name="wlk">元素,得到Element对象
    var form = document.wlk;
    但是,不太推荐这样做,最好还是显示的调用getElementsByName()来查找元素。注意,getElementsByName()是HTMLDocument类中的方法,所以使用通常如下:
    var el = document.getElementsByName("name");



    3.通过标签名查找:getElementsByTagName()
        getElementsByTagName("tagname")也返回NodeList对象,在NodeList对象中返回的元素按照在文档中的顺序排序的。所以可如下获取文档的第一个p元素:
    var p = document.getElementsByTagName("p")[0];
    HTML标签不区分大小写,故而在使用该方法是也不用区分大小写。如果传参数为通配符*,就返回文档中所有的元素。
    该方法给是Element对象的方法,所以你既可以在document上调用,也可以在element上调用
    像getElementsByName()一样,该方法对form、images等标签也可像操作属性一样操作。如:
    document.forms.wlk或者document.forms[1]。当然还是推荐显示调用getElementsByTagName()。


    4.通过class属性选取元素:getElementsByClassName()
        getElementsByClassName()方法基于class属性值中的标志符来选取成组的文档元素。类似getElementsByTagName(),在HTMl文档和HTML元素上都可调用getElementsByClassName(),它的返回值是NodeList对象,且是实时的。它的参数只需要一个字符串,但该字符串可以由多个空格隔开的标志符组成。只有当元素的class属性值包含指定的标志符时才匹配,不过标志符的顺序无关紧要。
    在标准模式下,该方法区分大小写,在兼容模式下,不区分大小写。


    5.通过css选择器选取元素:querySelectorAll()querySelector()
        querySelectorAll(),它接受包含一个css选择器的字符串参数,返回一个表示NodeList对象。注意,该NodeList对象不是实时的:它包含在调用时刻选择器所匹配的元素,但它并不更新后续文档的变化。
    如果没有匹配的元素,返回空的NodeList对象。如果选择器语法错误,将跑出一个异常。
    还有一个querySelector()方法,与querySelectorAll()工作原理一样,不过它只返回第一个匹配的元素,如果没有匹配的,返回null。
    这两个方法在element上也有定义,所有在元素上也可用
    注意,css定义了“:first-line”和“:first-letter”等伪元素,它们在文档中并不是实际元素,所以css选择器选取元素时不会匹配它们。
    querySelectorAll()是终极的选取元素的办法:它是一种非常强大的技术,通过它客户端JavaScript程序可以选择它们想要操作的元素。比如jQuery就是基于css选择器的查询作为编程核心,命名为$()。


    备注:
        document.all[]。
    该方法现在已经废弃不应该使用了。但是它在最开始引入时是革命性的,难免在比较老的网站或者程序中或遇到。
    document.all[0];//选取文档的第一个元素。
    document.all["bar"];//选取id或name为bar的元素。
    document.all.tags("div");//文档中所有的div元素。
    展开全文
  • 基于选取的作文特征,采用多元线性回归方法进行回归实验和稳定性交叉实验。实验表明,作文长度、词汇使用和成段表达方面的作文特征对作文得分具有较好的解释能力,多元线性回归方法应用于中国汉语水平考试自动作文...
  • 目前几乎所有主流的浏览器都支持position属性(inherit除外,inherit不支持所有包括IE8和之前版本IE浏览器,IE9、IE10还没测试过),以下是w3school对position五个值的解释: 其中absolute和relative是最常用的,...
  • 根据相干体技术原理和主要参数选取原则,对五阳矿区进行了以断层和陷落柱为主要研究对象的解释工作。应用实例表明:相干体技术可有效解决本区断层断点较多、切割关系复杂、空间展布规律难以把握和常规解释误差较大等...
  • 目前几乎所有主流的浏览器都支持position属性("inherit"除外,"inherit"不支持所有包括IE8和之前版本IE浏览器,IE9、IE10还没测试过),以下是w3school对position五个值的解释: 其中absolute和relative是最常用的...
  • 通常情况下我们会获取所选取对象的ID,通过循环及简单封装拼凑成一个长String传送过去,并在Service层解释再通过findByID获取实例并update 但今次我们需要将整个对象群完整传输至后台 其结构如下   选用谷歌...
  • 它可以看做是当前线程所执行字节码行号指示器字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行字节码指令,分支 循环 跳转 异常处理 线程恢复等基础功能都需要依赖这个计数器来完成j...

    1.5.3多核并行

    Lambda支持会极大改善目前Java语言不适合函数式编程的现状.函数式编程的一个重要优点就是天然适合并行运行.

    5644fc922270a0bd469de00ac94d8178.png

    2.2.1程序计数器(每条线程独立私有)

    程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器

    字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支 循环 跳转 异常处理 线程恢复等基础功能都需要依赖这个计数器来完成

    jvm的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现

    2.2.2 Java虚拟机栈(JVM stacks)

    stacks也是线程私有 描述的是java方法执行的内存模型,每个方法在执行的同时会创建一个栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。

    每一个方法从调用到执行完成的过程,就对应栈帧从入栈到出栈的过程

    在概念模型中,两个栈帧作为虚拟机栈的元素,相互之间是完全独立的,但是大多数虚拟机的实现里都会作一些优化处理,令两个栈帧出现一部分重叠。让下栈帧的部分操作数栈与上面栈帧的部分局部变量表重叠在一起,这样在进行方法调用返回时就可以共用一部分数据,而无须进行额外的参数复制传递了,重叠过程如下图:

    7c304b8bc9576b268c60406c5ac2d88b.png

    局部变量表存放八种基本数据类型、对象引用(reference类型,不一定是本身 也可能是指向对象地址的指针或者句柄)、returnAddress(指向字节码指令的地址)

    (64位的long和double会占用两个局部变量空间(Slot)(字宽),其他为1个)

    局部变量表的内存空间在编译期间完成分配(执行时不会改变空间大小)

    stackOverflowError:线程请求的栈深度大于虚拟机所允许的深度

    OutOfMemoryError:虚拟机栈动态拓展时无法申请到足够的内存

    2.2.3本地方法栈(为JVM使用到的Native方法服务)

    和虚拟机栈类似 区别是本地方法栈执行Native方法服务

    2.2.4 java堆(Heap)(唯一目的:存放对象实例)

    Java堆时JVM管理内存中最大的一块,java堆是被所有线程共享的一块内存区域,在JVM启动时创建

    Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做"GC堆"

    内存回收的角度:现在收集器基本都采用分代收集算法

    heap可以处于物理上不连续的内存空间中,只要逻辑上连续即可

    可以通过配置(-Xmx和-Xms)来拓展堆空间

    2.2.5 方法区(描述为堆的一个逻辑部分,但是与堆是分开的 Non-Heap)(HotSpot专属 永久代 Perm Generation)

    JDK1.7的HotSpot,已经把原本放在永久代的字符串常量池移出.

    各个线程共享的内存区域,用于存储已被加载的类信息,常量,静态变量,即时编译器编译后的代码。

    和heap一样不需要连续的内存和可以选择固定代销或者可拓展外,还可以选择不实现垃圾收集

    方法区的内存回收目标 主要针对常量池的回收和对类型的卸载。类型卸载的条件非常苛刻

    2.2.6 运行时常量池(Runtime Constant Pool)

    运行时常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用(发生时间在类加载后进入方法区时)

    通常 直接引用也会存储在运行时常量池中

    动态性,java语言并不要求常量一定只有编译期才能产生,运行期间也可能将新的常量放入池中(如String类的intern()方法)

    运行时常量池相遇Class文件常量池的另外一个重要特征是具备动态性(常量不是只有在编译期才会产生,如String.intern())

    intern()方法的目的是重用String对象,以节省内存消耗

    jdk1.7之前 常量池放在PERM区(属于方法区)使用引号声明的字符串都是会直接在字符串常量池中生成的,而new出来的String对象是放在堆里

    所以两者的内存地址肯定不一样,

    2.2.7 直接内存

    jdk1.4后加入NIO(New Input/Output)类,引入了一种基于通道与缓冲区的I/O方式,它可以使用native函数库直接分配堆外内存,,

    然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。可以避免在Java堆和Native堆中来回复制数据

    直接内存的分配不会受到Java堆大小的限制.避免大于物理内存的情况

    2.3.1对象的创建

    虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载

    解析和初始化过,如果没有,先执行相应的类加载过程,接下来为新生对象分配内存

    1.为对象分配空间的任务等同于把一块确定大小的内存从堆中划分出来。(两种方式由java堆是否规整决定《--由采用的垃圾收集器是否带有压缩功能决定)

    指针碰撞(堆中内存绝对规整)

    不规整,空闲和使用的内存相互交错,JVM必须维护一个列表,记录哪些内存块是可用的,分配时候找到一块足够大的分配给对象实例,这种分配方式被称为‘空闲列表’

    new

    2.并发创建对象(非线程安全)

    方案1:对分配内存空间的动作进行同步处理--实际上JVM采用CAS配上失败重试的方式保证更新操作的原子性

    方案2:把内存分配的动作按照线程划分在不同的空间中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)

    哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配心得TLAB时,才需要同步锁定。

    通过-XX:+/-UseTLAB

    内存分配完成后,需要将分配到的内存空间都初始化为零(不包括对象头:存放对象的各种信息),如果使用TLAB,这一工作过程也可以提前至TLAB分配时进行

    用以保证对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值

    2.3.2对象的内存布局

    对象在内存中存储的布局可以分为三个区域:对象头(Header),实例数据(Instance Data) 和对齐填充(Padding)

    Header:

    1.存储对象自身的运行时数据(Mark Word):hashCode,Gc age,线程持有的锁,偏向线程ID,偏向事件戳等

    2.类型指针(对象指向它的类元数据的指针,通过其确定是哪个类的实例):

    实例数据:

    存储代码中所定义的各种类型的字段内容,HotSpot虚拟机默认的分配策略为longs/doubles,ints,shorts/chars,bytes/booleans,oops(ordinary Object Pointers)

    (相同宽度的字段被分在一起),在这个前提下,父类中定义的变量会出现在子类之前。如果CompactFields参数值为true,那么子类之中较窄的变量也可能会插入父类变量的间隙中

    Padding:不是必然存在的,仅仅是占位符 HotSpotVm的自动内存管理系统要求对象的起始地址是8字节的整数倍,就是对象的大小必须是8字节的整数倍,

    而header是8的整数倍,因此当对象实例没有对齐,就通过对齐填充来补全

    2.3.3 对象的访问定位

    java程序需要通过栈上的reference数据来操作堆上的具体对象。由于reference类型在JVM规范中只规定了一个指向对象的引用,并未定义这个引用如何定位和访问具体位置,所以对象访问方式由具体虚拟机实现而定。主要有句柄和直接指针两种方式

    1.句柄访问:堆中划分一块内存来作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据和类型数据各自的具体地址信息

    优势:在对象被移动(GC中移动对象很常见)时只会改变句柄的实例数据指针,reference本身不需要修改

    abae0d54576148303854b474366e99a6.png

    2.直接指针:堆对象的布局中必须考虑如何放置访问类型数据的相关信息,reference中存储的直接是对象地址

    优势:速度快,节省了一次指针定位的时间开销,对象的访问在java中非常频繁,因此可以减少执行成本(Sun HotSpot虚拟机主要使用)

    2.4 OutOfMemoryError 异常                    (-Xms=-Xmx设置为一样 可以避免堆自动拓展)

    JVM启动参数(Run环境 arguments)-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8

    -XX:+HeapDumpOnOutOfMemoryError:可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析

    2.4.1 java堆溢出

    在对象数量到达最大堆得容量限制后就会产生内存溢出异常

    java.lang.OutOfMemoryError:Java heap space

    解决方法:一般的手段先通过内存映像分析工具(Eclipse Memory Analyzer)对Dump出来的堆转储快照进行分析,

    目的是确认内存中的对象是否是必要的(先分清楚是内存泄漏(Memory Leak)还是内存溢出(Memory Overflow))

    1.内存泄漏(堆内存无法释放造成系统内存的浪费):查看泄漏对象到GC Roots的引用链。就能找到泄漏对象是通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收他们的,就可以准备定位泄漏代码的位置

    2.如果不存在泄漏,即所有对象都必须存活,检查虚拟机的堆参数(-Xmx与-Xms)与物理内存对比是否需要上调,

    从代码上检查是否存在某些对象生命周期过长,持有状态时间过长的情况,尝试减少程序运行期的内存消耗

    2.4.2 虚拟机栈和本地方法栈溢出

    HotSpot不分区虚拟机栈和本地方法栈,因此栈容量只由-Xss参数设定

    1.StackOverflowError:如果线程请求的栈深度大于虚拟机所允许的最大深度(主)(阅读错误堆栈)

    2.OutOfMemoryError:如果虚拟机在拓展栈时无法申请到足够的内存空间

    操作系统分配给每个进程的内存是有限制的,虚拟机提供参数来控制Java堆和方法区的内存的最大值。

    剩余的内存为=2GB(操作系统限制)-Xmx(堆最大容量)-MaxPermSize(最大方法区容量)

    每个线程分配到的栈容量越大,可以建立的线程数量自然就越少,建立线程时就越容易把剩下的内存耗尽

    如果是建立过多线程导致的内存溢出,在不能减少线程数或者更换64位虚拟机的情况下,只能通过减少最大堆和减少栈容量来换取更多的线程

    2.4.3方法区和运行时常量池溢出 Perm(永久代)

    String.intern()是一个Native方法,它的作用是:

    如果字符串常量池已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用

    JDK1.6 intern()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中这个字符串实例的引用

    JDK1.7 intern()方法不会再复制实例,只是在常量池中记录首次出现的实例引用

    方法区用于存放Class的相关信息:类名,访问修饰符,常量池,字段描述,方法描述。

    方法区溢出(大量JSP或者动态产生JSP文件的应用,基于OSGI的应用(即使是同一个类文件,被不同的加载器加载也会视为不同的类))也是一种常见的内存溢出异常,一个类要被GC回收掉,判断条件比较苛刻。在经常动态生成大量Class的应用中,需要注意类的回收

    2.4.4 本机直接内存溢出

    DirectMemory容量可以通过-XX:MaxDirectMemorySize指定,默认与-Xmx一样

    展开全文
  • 当字节码解释器在工作时候,就是通过改变程序计数器值来选取下一条要执行代码,例如分支、循环、跳转、异常处理都是通过程序计数器变更来实现,当执行方法为Native方法时程序计数器为空(Undefined)...

    jvm内存区域的划分以及运行时对象存储位置


    jvm的内存区域分为程序计数器、本地方法栈、虚拟机栈、堆、方法区

    程序计数器

    当字节码解释器在工作的时候,就是通过改变程序计数器的值来选取下一条要执行的代码,例如分支、循环、跳转、异常处理都是通过程序计数器的值的变更来实现的,当执行的方法为Native方法时程序计数器为空(Undefined)。由于Java的多线程是通过线程轮流切换并分配处理器时间来实现的,所以在任意一个确定的时刻,一个处理器都只会执行一个线程中的指定,为了在线程切换后回到原来位置,所以程序计数器也是线程私有的。

    虚拟机栈

    虚拟机栈也是线程私有的,虚拟机栈描述的是java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息,一个方法从调用到执行结束的过程,就是对应栈帧从入栈到出栈的过程。
    局部变量表存放了编译器可知的各种基本数据类型(八大基本数据类型)、对象引用(reference类型,不等同于对象本身,可能只是一个指向对象起始地址的引用指针,也可能是一个代表对象的句柄或者其他相关属性)和returnAddress(指向一条字节码指令的地址)类型。
    其中64位长度的long和double类型会占两个局部变量空间(Slot),其余数据只占1个。局部变量表所需内存在编译阶段就分配完成,所以在进入一个方法时,这个方法需要在栈里分配多大局部变量表空间时确定的,在方法运行期间不会改变局部变量表的大小。
    如果线程请求栈的深度大于虚拟机栈所允许的深度,则会报出StackOverflowError异常。但是现在大多数的虚拟机都是可以动态扩展的,但是如果在扩展时无法申请到足够的内存,依然会报出OutOfMemoryError异常。

    本地方法栈

    本地方法栈和虚拟机栈的作用几乎相同,不同之处在于虚拟机栈执行的是Java方法,也就是字节码。而本地方法栈中执行的是native方法,在虚拟机规范中并未对本地方法栈的方法使用的语言、使用方式和数据结构之间有强制规定,因此虚拟机可以自由实现它。例如Sun公司的HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一,同样也会报出StackOverflowError和OutOfMemoryError异常。

    Java堆 Java Heap是虚拟机所管理内存中最大的一块。java堆是被所有线程共享的一块区域,在虚拟机启动时创建。Java heap存在的目的就是为了存放对象实例,几乎所有的对象实例都要在堆里分配内存(本来没有几乎,但是JIT编译器和逃逸技术的发展,栈上分配、标量替换优化技术会产生一些变化)。
    java堆是垃圾收集器的主要作用区域,很多时候也被称为GC堆。从内存回收的角度看,现在的收集器基本上都使用分代收集算法,所以可以将堆划分为新生代和老年代,再细致一点有Eden空间、From Survivor空间、To Survivor空间。
    从内存分配角度看,线程共享的堆可能划分出多个线程私有的缓冲区,不管如何划分,都与存储内容无关,无论哪个区域,存储的都是对象实例,进一步划分是为了更好的分配内存或者回收内存。
    Java堆可以处在物理上不连续但是逻辑上连续的空间,就像我们的磁盘空间,既可以固定大小,也可以扩展,不过当前主流虚拟机都按照可扩展来实现,通过-Xmx和-Xms来控制,如果堆中没有内存分配实例,并且堆也无法扩展的时候,将会抛出OutOfMemoryError异常。

    方法区

    方法区和Java堆一样,都是属于线程共享区域,它用于存储虚拟机已经被加载的类信息、常量、静态变量、即时编译器编译后的代码。虽然Java虚拟机规范吧方法区和堆描述为一个逻辑连续的部分,但是方法区还有一个名字叫Non-Heap非堆,目的是将其同Java堆区分开来。

    运行时常量池

    方法区的一部分,class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译其生成的字面量和符号引用,这部分内容将在加载后进入方法区的运行时常量池存放。(直接内存也会存储在运行时常量池里)
    运行时常量池相对于class文件的常量池最重要的一个特性就是具备动态性,Java语言并不要求常量一定只有在编译器产生,也就是并不一定非要是class文件常量池的预置的变量才能进入常量词中,运行期也可能将新的常量放在常量池中,这种特性大多数可以使用System.intern()方法。
    运行时常量池是方法区的一部分,所以也会受到内存限制,当常量池再也无法申请到内存,则会报出OutOfMemoryError异常。

    直接内存

    直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机中规范的区域。JDK1.4中新加入了NIO类,这是基于通道和缓存区的IO方式,它可以通过Native函数直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象来作为这块内存的引用进行操作,避免Java堆和Native堆的来回复制。
    本机直接分配的内存不会受到Java堆大小的限制,但是仍会受到本机总内存(包括RAM以及SWAP或者分页文件)大小以及处理器寻址空间的限制,通过-Xmx分配Java虚拟机内存时要避免忽略了直接内存,而导致各个内存区域之和大于物理总内存,从而倒是内存扩展时出现的OutOfMymeryError异常。

    展开全文
  • 每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要和重复出现设计。我们目标是将设计经验以人们能够有效利用形式记录下来。鉴于此目的,我们编写了一些重要设计模式,并以编目分类形式将...
  • 字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行字节码指令,分支、循环、跳转、异常处理、线程回复等基础工作都需要依赖这个计数器完成。2. Java虚拟机栈生命周期与线程相同。其中描述是...

    java内存区域

    Java 虚拟机所管理的内存将会包括下几个运行时数据区域:

    b206154d9e43eec2efdf4ed847d831ce.png

    程序计数器

    一块较小的内存空间,当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程回复等基础工作都需要依赖这个计数器完成。

    2. Java虚拟机栈

    生命周期与线程相同。其中描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出入等信息。

    局部变量表存放编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用。 其中64位长度的double和long类型的数据会占用2个局部变量空间,其余的占用一个。

    Java虚拟机规范中,对这个区域规定了两种异常情况:如果线程请求的栈的深度大于虚拟机运行的深度,将跑出StackOverFlowError异常;如果虚拟机栈可以动态扩展,如果扩展无法申请到足够的内存,就会抛出OutOfMemoryError异常。

    3. 本地方法栈

    本地方法栈与虚拟机栈所发挥的作用是非常相似的。区别为,虚拟机栈执行Java方法服务,本地方法栈为虚拟机使用到的Native方法服务。虚拟机规范对它没有强制规定,有些虚拟机将本地方法栈、Java虚拟机栈合二为一。抛出异常与Java虚拟机栈一样。

    4. Java堆

    Java堆是Java虚拟机管理内存最大的一块。是被所有线程共享的一块内存区域,在虚拟机启动时创建。此区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

    java堆也是垃圾收集器管理的主要区域,很多时候称为GC堆。Java堆可以细分为:新生代和老年代。

    5. 方法区

    方法区也是被所有线程共享的一块内存区域,它被用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

    6. 运行时常量池

    运行时常量池是方法区的一部分。用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池存放。

    7. 直接内存

    直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。但是这部分内存被频繁地使用。而却也可能导致OutIfMemoryError异常出现。

    JDK1.4引入NIO(New Input/Output)类,引入了一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

    对象的创建

    虚拟机遇到一条new指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表类是否已经被加载、解析和初始化过。如果没有,就必须先执行对应的类加载过程。检查完后,接下来虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定,分配空间就是将一块确认大小的内存从Java堆中划分出来。

    假如Java堆中的内存是绝对规整的,所有用过的内存在一边,没有使用过的在另一边,中间放一个指针作为分界点的指示器,分配内存只需要移动指针,这种分配方式叫“指针碰撞”。假如Java堆中的内存不是规整的,虚拟机必须维护一个列表,记录哪些内存块是可用的,分配的时候从列表找一块足够大的空间划分给对象,并更新列表记录,这种分配方式叫“空闲列表”。

    还有一个问题是,并发情况下创建对象会频繁修改指针位置,线程不安全。解决这个问题有两种方案:一种是对分配内存空间的动作进行同步处理。另一种是把内存的分配动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB)。那个线程需要分配内存,就在哪个线程的TLAb上分配,只有TLAB用完分配新的TLAB时才需要同步锁定。

    接下来,虚拟机对对象进行必要的设置,例如这个对象时哪一个类的实例、如何才能找到类的元数据信息。

    1. 对象的内存布局

    虚拟中,对象在内存中存储的布局可以分为3块区域:对象头、实例数据和对齐填充。

    对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这部分数据长度在32位和64位虚拟机中分别为32bit和64bit,官方称为“Mark Word”。

    Mark Word设计为一个非固定的数据结构,以便在极小的空间内存存储尽量多的信息,它会根据对象的状态服用自己的存储空间。

    对象头的另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例。假如,对象是一个数组,那么对象头中还必须有一块用于记录数组长度的数据。因为虚拟机可以通过普通java对象的元数据信息确定java对象的大小,但是从数组的元数据中却无法确定数组的大小。

    实例数据部分是对象真正存储的有效信息,也是代码中定义的各种类型的字段内容。从父类继承、在子类定义都需要记录起来。这部分的存储顺序会受到虚拟机分配策略参数和字段在Java源码中定义顺序的影响。

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

    2. 对象的访问定位

    目前主流的访问方式主要是句柄和直接指针两种。

    句柄访问,Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。

    55ebd8a2c8c7d6e92c7222ec68cda50a.png

    直接指针访问,Java堆对象的布局中就必须考虑如何防止访问类型数据的相关信息,而reference中存储的直接就是对象的地址。

    bdcdedd83541a6c085733e1ea3c6988b.png

    展开全文
  • 业务是需要将前台jQuery easyUI DataGrid列表中所选若干行数据传到后台进行update操作通常情况下我们会获取所选取对象的ID,通过循环及简单封装拼凑成一个长String传送过去,并在Service层解释再通过findByID...
  • java内存区域 Java 虚拟机所管理内存将会包括下几个运行时数据区域: 程序计数器 ...字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行字节码指令,分支、循环...
  • 是一块很小内存空间,可以看作是当前线程所执行字节码行号指示器,字节码解释器就是就是通过改变程序计数器里面值来选取下一条需要执行字节码指令,跳转啊,循环啊。同样线程切换也是需要上一次线程所...
  • 字节码解释器工作时通过改变这个计数器值来选取下一条需要执行字节码指令,分支、循环、跳转都需要依赖这个计数器来完成。 如果一个线程正在执行java方法,则计数器记录正在执行虚拟机字节码指令地址;...
  • 参考:《深入理解Java虚拟机》周志明著 一、JVM数据区 1. 程序计数器:   当前线程所执行...字节码解释器工作时就是通过改变计数器值来选取下一条要执行字节码命令   唯一一个不会抛出任何内存溢出(Ou...
  • 以json 传递整行对象到后台

    千次阅读 热门讨论 2014-12-31 23:57:24
    业务是需要将前台jQuery ... 通常情况下我们会获取所选取对象的ID,通过循环及简单封装拼凑成一个长String传送过去,并在Service层解释再通过findByID获取实例并update  但今次我们需要将整个对象群完整传输至
  • 字节码解释器工作时需要通过改变这个计数器值来选取下一条要执行字节码指令。 多线程执行任务时,由于内核是通过切换来模拟异步操作,所以每条线程都需要一个独立程序计数器,以便于线程切换后再次回到本线
  • 目录 一、前言 二、对象创建 三、对象定位方式 一、前言 Java虚拟机(JVM)内部定义了程序在...这块内存区域很小,它是当前线程所执行字节码行号指示器,字节码解释器通过改变这个计数器值来选取下一条需...
  • 1.JVM运行时结构 Java 运行时数据区域有程序计数器、Java虚拟机栈、本地方法栈、Java堆和方法区。...在虚拟机概念模型中,字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行...
  • Oracle视图解释

    千次阅读 2011-03-02 09:41:00
    Oracle数据库对象分为五种:表,视图,序列,索引和同义词。  视图是基于一个表或多个表或视图逻辑表,本身不包含数据,通过它可以对表里面数据进行查询和修改。视图基于表称为基表。  视图是...
  • 爬虫基础之数据解释

    2019-03-16 23:46:29
    目录 XPath语法和lxml模块 什么是XPath? XPath开发工具 XPath语法 选取节点: 谓语: 通配符 选取多个路径: 运算符: lxml库 基本使用: 从文件中读取html代码:...四个常用的对象 1. Tag 2. Naviga...
  • 程序计数器是一块较小线程私有内存区域,存储当前线程所执行字节码指令地址,字节码解释器就是通过改变该计数器值来选取下一条需要执行字节码指令;如果线程正在执行是一个java方法,程序计数器记录...
  • 原标题:JVM 内存区域与GC*作者:青芒@...字节码解释器工作时候就是通过改变这个计数值来选取下一条要执行字节码指令。1.2 虚拟机栈(java方法栈)线程私有,java方法执行时内存模型,每个方法执行时候都会创...
  • JVM之内存和对象创建过程

    千次阅读 2018-08-29 14:32:10
    1.5.3多核并行 Lambda支持会极大改善目前Java语言不适合函数式编程现状.函数式编程一个重要...字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行字节码指令,分支 循环 跳转 异常处理 线...
  • 在虚拟机概念模型里,字节码解释器工作时就是通过改变这个计数器值来选取下一条需要执行字节码指令、分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 虚拟机栈 同样是线程私有。
  • 在Java虚拟机概念模型里[1],字节码解释器工作时就是通过改变这个计数器 值来选取下一条需要执行字节码指令,它是程序控制流指示器,分支、循环、跳转、异常处 理、线程恢复等基础功能都需要依赖这个计数器...
  • 一、运行时数据区域 Java虚拟机在执行Java程序过程中会把它所管理内存划分为若干个不同数据区域。...字节码解释器通过改变计数器值来选取下一条要执行指令。 每条线程都需要有一个独立程序...
  • 在虚拟机概念模型里字节码解释器就是通过改变计数器选取下一条需要执行字节码指令,分支,循环,跳转,异常,线程恢复等基础功能依赖于此。 java虚拟机多线程通过 线程轮流切换并分配处理器执行时间实现 ...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 147
精华内容 58
关键字:

对象选取的解释