动力节点教你java内存分配

动力节点教你java内存分配

动力节点

java数据在内存中存储详解

博客分类: JAVA 1. 有这样一种说法,如今争锋于IT战场的两大势力,MS一族偏重于底层实现,Java 一族偏重于系统架构。说法根据无从考证,但从两大势力各自的社区力量和图书市场已有佳作不难看出,此说法不虚,但掌握Java的底层实现对Java程序员来说是至关重要的,本文介绍了Java中的数据在内存中的存储。 2内存中的堆(stack)与栈(heap) Java程序运行时有6个地方可以存储数据,它们分别是寄存器、栈、堆、静态存储、常量存储和非RAM存储,主要是堆与栈的存储。 【随机存储器:Random Access Memory】 栈与堆都是Java用来在RAM中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。另外,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。 【寄存器位于CPU中】 3Java中数据在内存中的存储 3.1基本数据类型的存储 Java的基本数据类型共有8种,即int,short,long,byte,float,double, boolean,char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a=3;long b=255L;的形式来定义的,称为自动变量。值得注意的是:自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a=3;这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。

JVM原理以及JVM内存管理机制

一、 JVM简介 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成, 首先来说一下JVM工作原理中的jdk这个东西, .JVM 在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机. 操作系统装入JVM是通过jdk中Java.exe来完成。 通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 4.调用JNIEnv实例装载并处理class类。 对于JVM自身的物理结构,我们可以从下图了解:

JVM的一个重要的特征就是它的自动内存管理机制,在执行一段Java代码的时候,会把它所管理的内存划分 成几个不同的数据区域,其中包括: 1. 程序计数器,众所周知,JVM的多线程是通过线程轮流切换并 分配CPU执行时间的方式来实现的,那么每一个线程在切换 后都必须记住它所执行的字节码的行号,以便线程在得到CPU 时间时进行恢复,这个计数器用于记录正在执行的字节码指令的地址,这里要强调的是“字节码”,如果执行的是Native方法,那么这个计数器应该为null; 2.

3. Java计算栈,可以说整个Java程序的执行就是一个出栈入栈 的过程,JVM会为每一个线程创建一个计算栈,用于记录线程中方法的调用和变量的创建,由于在计算栈里分配的内存出栈后立即被抛弃,因此在计算栈里不存在垃圾回收,如果线程请求的栈深度大于JVM允许的深度,会抛出StackOverflowError 异常,在内存耗尽时会抛出OutOfMemoryError异常; 4. Native方法栈,JVM在调用操作系统本地方法的时候会使用到 这个栈; 5. Java堆,由于每个线程分配到的计算栈容量有限,对于可能会 占据大量内存的对象,则会被分配到Java堆中,在栈中包含了指向该对象内存的地址;对于一个Java程序来说,只有一个Java堆,也就是说,所有线程共享一个堆中的对象;由于Java堆不受线程的控制,如果在一个方法结束之后立即回收这个方法使用到的对象,并不能保证其他线程是否正在使用该对象;因此堆中对象的回收由JVM的垃圾收集器统一管理,和某一个线程无关;在HotSpot虚拟机中Java堆被划分为三代:o新生代,正常情况下新创建的对象会被分配到新生代,但如果对象占据的内存足够大以致超过了新生代的容量限 制,也可能被分配到老年代;新生代对象的一个特点是最 新、且生命周期不长,被回收的可能性高;

java虚拟内存

目录 java虚拟机内存管理机制(一):JVM内存管理总结【分享】收藏 (1) java虚拟机内存管理机制(二):了解JVM的内存管理与垃圾回收收藏 (5) java虚拟机内存管理机制(三):我主管写的一些jvm内存管理知识收藏 (8) java虚拟机内存管理机制(一):JVM内存管理总结【分享】收藏 近期看了看Java内存泄露的一些案例,跟原来的几个哥们讨论了一下,深入研究发现JVM 里面还是有不少以前不知道的细节,这里稍微剖析一下。先看一看JVM的内部结构—— 如图所示,JVM主要包括两个子系统和两个组件。两个子系统分别是Class loader子系统和Execution engine(执行引擎) 子系统;两个组件分别是Runtime data area (运行时数据区域)组件和Native interface(本地接口)组件。 Class loader子系统的作用:根据给定的全限定名类名(如https://www.360docs.net/doc/f918032888.html,ng.Object)来装载class文件的内容到Runtime data area中的method area(方法区域)。Java程序员可以extends https://www.360docs.net/doc/f918032888.html,ng.ClassLoader类来写自己的Class loader。

Execution engine子系统的作用:执行classes中的指令。任何JVM specification实现(JDK)的核心都是Execution engine,不同的JDK例如Sun 的JDK 和IBM的JDK好坏主要就取决于他们各自实现的Execution engine的好坏。 Native interface组件:与native libraries交互,是其它编程语言交互的接口。当调用native方法的时候,就进入了一个全新的并且不再受虚拟机限制的世界,所以也很容易出现JVM无法控制的native heap OutOfMemory。 Runtime Data Area组件:这就是我们常说的JVM的内存了。它主要分为五个部分—— 1、Heap (堆):一个Java虚拟实例中只存在一个堆空间 2、Method Area(方法区域):被装载的class的信息存储在Method area的内存中。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件内容并把它传输到虚拟机中。 3、Java Stack(java的栈):虚拟机只会直接对Java stack执行两种操作:以帧为单位的压栈或出栈 4、Program Counter(程序计数器):每一个线程都有它自己的PC寄存器,也是该线程启动时创建的。PC寄存器的内容总是指向下一条将被执行指令的饿地址,这里的地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。 5、Native method stack(本地方法栈):保存native方法进入区域的地址 以上五部分只有Heap 和Method Area是被所有线程的共享使用的;而Java stack, Program counter 和Native method stack是以线程为粒度的,每个线程独自拥有自己的部分。 了解JVM的系统结构,再来看看JVM内存回收问题了—— Sun的JVM Generational Collecting(垃圾回收)原理是这样的:把对象分为年青代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的算法。(基于对对象生命周期分析)

Java内存区域划分、内存分配原理

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 Java 内存区域划分、内存分配原理 2014/11/16 2448 运行时数据区域 Java 虚拟机在执行Java 的过程中会把管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程 的启动而存在,而有的区域则依赖线程的启动和结束而创建和销毁。 Java 虚拟机包括下面几个运行时数据区域: 程序计数器 程序计数器是一块较小的区域,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的模型里,字节码指示器就是通过改变程序计数器的值 来指定下一条需要执行的指令。分支,循环等基础功能就是依赖程序计数器来完成的。 由于java 虚拟机的多线程是通过轮流切换并分配处理器执行时间来完成,一个处理器同一时间只会执行一条线程中的指令。为了线程恢复后能够恢复正确的 执行位置,每条线程都需要一个独立的程序计数器,以确保线程之间互不影响。因 此程序计数器是“线程私有”的内存。 如果虚拟机正在执行的是一个Java 方法,则计数器指定的是字节码指令对应的地址,如果正在执行的是一个本地方法,则计数器指定问空undefined。程序计数器区域是Java 虚拟机中唯一没有定义OutOfMemory 异常的区域。 Java 虚拟机栈 和程序计数器一样也是线程私有的,生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用的过程就对应 一个栈帧在虚拟机栈中从入栈到出栈的过程。

Java工程师就业前景分析

2017年Java工程师就业前景分析 新年伊始,2017年不期而至。这是找工作的热门时期,据前 程无忧、智联招聘等招聘网站的数据分析显示,Java软件工程师需求量已达到20余万人,比上一年增长了近百分之三十。综合来看, 近几年的Java开发的就业前景还是很不错的,市场需求依然很大, 很多企业还未招聘到自己最需要的技术人员,所以趁现在赶快来学习吧,学好Java软件开发技术,实现高薪就业,轻松当职场白领。 随着新兴互联网行业的迅速发展,传统企业的互联网化,Java工程师的需求量不断增加,现在已经成为了高度紧缺的工作岗 位之一,薪水待遇也是相当不错的。所以学习Java知识,成为一名Java软件工程师发展前途是非常光明的,学好Java,可以利用Java 开发软件改变你的生活和工作,走上自已的职场白领和金领的道路 上。让自己在软件开发中享受了乐趣,在使用软件中享受了生活。 Java发展如此迅速,很多人都想进入该行业,但是又不知 道如何实现就业,动力节点现在给零基础学员提供了快速进入该行业 的机会,没钱没关系,先学习就业后再付学费,没学会没关系,提供 免费重学制度,哪里不会重新再学,学会为止。 动力节点,在2017年来看,Java软件开发行业依然一片光明,成为Java软件工程师依然是一个不错的选择,来这里学习Java 技术,专业的Java培训机构,专注Java培训八年多了,国内高端IT培训品牌,专注于Java教育事业的培训,只做一科。专业的师资

团队,强大的师资力量,各个Java老司机,Java开发授课经验十年以上,均为硕士学位,拥有先进的教学体系和专业的就业辅导课程,零基础入学,从低级到高级Java培训课程,学完推荐就业,只要你肯认学,高薪就业不是梦想,只要你肯努力,一切皆有可能。 [2017年Java工程师就业前景分析]

JVM调优与JAVA内存管理总结

JVM调优总结 基本回收算法 1.引用计数(Reference Counting) 比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。 2.标记-清除(Mark-Sweep) 此算法执行分两阶段。第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。此算法需要暂停整个应用,同时,会产生内存碎片。 3.复制(Copying) 此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。 4.标记-整理(Mark-Compact) 此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。 5.增量收集(Incremental Collecting) 实施垃圾回收算法,即:在应用进行的同时进行垃圾回收。不知道什么原因JDK5.0中的收集器没有使用这种算法的。 6.分代(Generational Collecting) 基于对对象生命周期分析后得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同生命周期的对象使用不同的算法(上述方式中的一个)进行回收。现在的垃圾回收器(从J2SE1.2开始)都是使用此算法的。 分代垃圾回收详述 如上图所示,为Java堆中的各代分布 Young(年轻代) 年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以

在C 中实现JAVA的存储管理机制

在C 中实现JAVA的存储管理机制 众所周知,JAVA语言最明显的优势在于用它设计的程序可以广泛地运行于互联网上所有安装了VM解释器的计算机上。然而,如今JAVA之所以在市场上如此流行,还得益于它的另一卖点:它提供了安全可靠和使用方便的存储管理机制。这是部分编程人员将它与其前身 C 语言对比后所得出的结论。本文将针对两种语言的内存(以对象为单位)使用机制,通过从灵活性、易用性和效率三个方面的比较,来证明这样一个事实:在C 中可以实现与JAVA一样的存储管理机制。 注:① C 的“指针使用”一列中并未列出形如*Instance的使用,因为这样做的实质不是指针使用; ②“指针复制”是指使得两个对象今后使用相同的一块内存区域,任何对此区域的修改同时会反映到这两个对象上; ③“内容复制”则指拷贝两个对象各自的存储区域,拷贝后内容相同,但各自保留自己的存储区,以后对任一者的修改不会影响另一者。 从上表可以看出,除了对象销毁机制以外,JAVA的对象其实是从C 中的对象和指针共同继承而来的。 但是,很多极力提倡JAVA语言的人似乎没有意识到这种关系。他们批评C 指针的概念太难被初学者接受。的确,对初学者来说,接受计算机存储器和指针的概念并不是轻而易举的事。事实上,很多程序员都经历过这样一个迷惘的阶段。但这并不意味着存在一种对存储器的解释可以完全避免“指针”这一概念——在JAVA语言中也是如此。现在有很多讲解JAVA语言的.教材,但真正能够从头到尾不出现“指针”或者类似概念(不包括抨击 C 语言时的使用)的,又有几本呢? 特别地,JAVA初学者由于理解的障碍,经常提出像这样的问题:“为什么像int、

4.实例变量和类变量内存分配

实例变量和类变量内存分配 Java向程序员许下一个承诺:无需关心内存回收,java提供了优秀的垃圾回收机制来回收已经分配的内存。大部分开发者肆无忌惮的挥霍着java程序的内存分配,从而造成java程序的运行效率低下! java内存管理分为两方面: 1,内存的分配:指创建java对象时,jvm为该对象在堆内存中所分配的内存空间。 2,内存的回收:指当该java对象失去引用,变成垃圾时,jvm的垃圾回收机制自动清理该对象,并回收该对象占用的内存。 jvm的垃圾回收机制由一条后台线程完成。不断分配内存使得系统中内存减少,从而降低程序运行性能。大量分配内存的回收使得垃圾回收负担加重,降低程序运行性能。 一,实例变量和类变量(静态变量) java程序的变量大体可分为成员变量和局部变量。 其中局部变量有3类:形参、方法内的局部变量、代码块内的局部变量。 局部变量被存储在方法的栈内存中,生存周期随方法或代码块的结束而消亡。 在类内定义的变量被称为成员变量。没使用static修饰的称为成员变量,用static修饰的称为静态变量或类变量。 1.1实例变量和类变量的属性 在同一个jvm中,每个类只对应一个Class对象,但每个类可以创建多个java对象。 【其实类也是一个对象,所有类都是Class实例,每个类初始化后,系统都会为该类创建一个对应的Class实例,程序可以通过反射来获取某个类所对应的Class实例(Person.class 或Class.forName(“Person”))】 因此同一个jvm中的一个类的类变量只需要一块内存空间;但对实例变量而言,该类每创建一次实例,就需要为该实例变量分配一块内存空间。 非静态函数需要通过对象调用,静态函数既可以通过类名调用,也可以通过对象调用,其实用对象调用静态函数,底层还是用类名调用来实现的! 1.2实例变量的初始化时机 对实例变量而言,它属于java对象本身,每次创建java对象时都需要为实例变量分配内存空间,并执行初始化。

基于java的学生信息管理系统设计与实现

基于java的学生信息管理系统设计与实现 基于java的学生信息管理系统设计与实现摘要:利用计算机进行学生信息管理,不仅能够保证准确、无误、快速输出,而且还可以利用计算机对有关信息进行查询,检索迅速、查找方便、可靠性高、存储量大、保密性好。本设计就是一个为实现信息化管理而开发的信息管理系统,能够进行信息存储、查询、修改等能功。该系统由六个模块构成,包括学生管理系统的主界面模块、学生信息管理模块、课程信息管理模块、成绩信息管理模块、信息查询模块和数据库操作模块。通过这些模块的有机结合,能方便的对学生信息进行综合管理,从而实现了信息化管理的目的。由于本人的能力有限,设计过程中难免有不足之处,设计中的存在问题本人将在日后进一步修改,以便让程序的设计更加完善。 关键词:oracle;异常处理;关系模型 目录

1 引言 1.1背景及意义 学生信息管理系统是一个教育单位不可缺少的部分。一个功能齐全、简单易用的信息管理系统不但能有效地减轻学校相关工作人员的工作负担,它的内容对于学校的决策者和管理者来说都至关重要。所以学生信息管理系统应该能够为用户提供充足的信息和快捷的查询手段。但一直以来人们使用传统人工的方式管理文件档案、统计和查询数据,这种管理方式存在着许多缺点,如:效率低、保密性差、人工的大量浪费;另外时间一长,将产生大量的文件和数据,这对于查找、更新和维护都带来了不少困难。随着科学技术的不断提高,计算机科学日渐成熟其强大的功能已为人们深刻认识,它已进入人类社会的各个领域并发挥着越来越重要的作用。 作为计算机应用的一部分,使用计算机对学校的各类信息进行管理,具有手工管理无法比拟的优点。例如:检索迅速、查询方便、效率高、可靠性好、存储量大、保密性好、寿命长、成本低等。利用计算机进行学生信息管理,不仅能够保证准确、无误、快速输出,而且还可以利用计算机对有关信息进行查询,检索迅速、查找方便、可靠性高、存储量大、保密性好。要科学地实现信息化管理,开发一个适合学校的,能够进行信息存储、查询、修改等功能的信息管理系统是十分重要的。这些优点能够极大地提高学校信息管理的效率,也是一个单位科学化、正规化管理,与世界接轨的重要条件。 本系统是将现代化的计算机技术和传统的教学、教务工作相结合,按照学院的工作流程设计完成的。通过一个简化的学生信息管理系统,使学生信息管理工作系统化、规范化、自动化,从而达到提高学生信息管理效率的目的。本课题就是针对便于学生信息管理的问题而设计的一个管理系统。 1.2 实验技术选择 本课题设计主要运用的技术有两个:java项目开发和oracle对数据库的操作。这里主要介绍本课题为什么选用这两个开发技术: ⑴首先了解一下Java语言特点

java内存空间详解

硬盘 heap stack Data code 内存 程序 操作系统代码 程序代码 New ,在堆里面为属性分配空间,初始化(String 默认值为null ) 声明的时候非配空间,初始值为null (局部变量,方法参数) 全局变量 存放程序所需要的代码 类变量,全局字符串,常量存放在数据段

Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java 在内存分配方面的知识。一般Java在内存分配时会涉及到以下区域: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 ◆堆:存放用new产生的数据 ◆静态域:存放在对象中用static定义的静态成员 ◆常量池:存放常量

◆非RAM存储:硬盘等永久存储空间 Java内存分配中的栈 在函数中定义的一些基本类型的变量数据和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 Java内存分配中的堆 堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。引用变量就相当于是为数组或者对象起的一个名称。 引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是Java 比较占内存的原因。 实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针! 常量池(constant pool) 常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值(final)还包含一些以文本形式出现的符号引用,比如: ◆类和接口的全限定名; ◆字段的名称和描述符; ◆方法和名称和描述符。 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和

--动力节点之java的知识点归纳总结

1. 基本数据类型 整形: byte 1 个字节 short 2 个字节 int 4个字节 long 8个字节 字符: char 2个字节 浮点数: float 4个字节 double 8个字节 布尔: boolean 1个字节 2.java 7 新增二进制整数 以0b或者0B开头 3.java中字符时16位的Unicode编码方式,格式是'\uXXXX',其中xxxx代表一个十六进制整数 4.java中规定了正无穷大、负无穷大和零 正无穷大= 一个正数除以0 负无穷大= 一个负数除以零 0.0 除以0.0 或者对一个负数开方得到一个非数 5. 在java中布尔类型只能是true和false 6. 在java中没有多维数组 动力节点

看似像C语言中的多维数组不是真正的数组,比如 a[3][4] , a[0] a[1] a[2] 是真实存在的,装的是地址,和 c语言中动态分配为的数组一样 int [][] b = new int[3][4] 7. Java中带包的编译方法 javac -d . Hello.java 会在当前目录下生成目录树 运行 java 包名字.类名字 8. Java多态中的对象的filed 不具有多态性,如父类对象 = new 子类(),对象.field 是调用的父类的,即使子类中覆盖了该字段。 9. instanceof 运算符 格式:引用变量名 instanceof 类名(或者接口)他用于判断前面的对象是否是后面对象的类,子类、实 现类的实例,是返回true,否者返回false 10. Java 中基本数据类型和对应封装类之间的转化 int a = 1; Integer A = new Integer(a); a = A.intValue(); 其他的类型也是这样的。 11.单例(singleton)类例子 复制代码代码如下: class Singleton { private static Singleton instance; private Singleton(){} public static Singleton getInstance() { 动力节点

java程序的内存分配

JAVA 文件编译执行与虚拟机(JVM)介绍 Java 虚拟机(JVM)是可运行Java代码的假想计算机。只要根据JVM规格描述将解释器移植到特定的计算机上,就能保证经过编译的任何Java代码能够在该系统上运行。本文首先简要介绍从Java文件的编译到最终执行的过程,随后对JVM规格描述作一说明。 一.Java源文件的编译、下载、解释和执行 Java应用程序的开发周期包括编译、下载、解释和执行几个部分。Java编译程序将Java源程序翻译为JVM可执行代码?字节码。这一编译过程同C/C++的编译有些不同。当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而产生的。因此,在编译过程中,编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创立内存布局,然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可移植性和安全性。 运行JVM字节码的工作是由解释器来完成的。解释执行过程分三部进行:代码的装入、代码的校验和代码的执行。装入代码的工作由"类装载器"(class loader)完成。类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被其调用的类。当类装载器装入一个类时,该类被放在自己的名字空间中。除了通过符号引用自己名字空间以外的类,类之间没有其他办法可以影响其他类。在本台计算机上的所有类都在同一地址空间内,而所有从外部引进的类,都有一个自己独立的名字空间。这使得本地类通过共享相同的名字空间获得较高的运行效率,同时又保证它们与从外部引进的类不会相互影响。当装入了运行程序需要的所有类后,解释器便可确定整个可执行程序的内存布局。解释器为符号引用同特定的地址空间建立对应关系及查询表。通过在这一阶段确定代码的内存布局,Java很好地解决了由超类改变而使子类崩溃的问题,同时也防止了代码对地址的非法访问。 随后,被装入的代码由字节码校验器进行检查。校验器可发现操作数栈溢出,非法数据类型转化等多种错误。通过校验后,代码便开始执行了。 Java字节码的执行有两种方式: 1.即时编译方式:解释器先将字节码编译成机器码,然后再执行该机器码。 2.解释执行方式:解释器通过每次解释并执行一小段代码来完成Java字节码程序的所有操作。 通常采用的是第二种方法。由于JVM规格描述具有足够的灵活性,这使得将字节码翻译为机器代码的工作 具有较高的效率。对于那些对运行速度要求较高的应用程序,解释器可将Java字节码即时编译为机器码,从而很好地保证了Java代码的可移植性和高性能。 二.JVM规格描述 JVM的设计目标是提供一个基于抽象规格描述的计算机模型,为解释程序开发人员提很好的灵活性,同时也确保Java代码可在符合该规范的任何系统上运行。JVM对其实现的某些方面给出了具体的定义,特别是对Java可执行代码,即字节码(Bytecode)的格式给出了明确的规格。这一规格包括操作码和操作数的语法和数值、标识符的数值表示方式、以及Java类文件中的J ava对象、常量缓冲池在JVM的存储映象。这些定义为JVM解释器开发人员提供了所需的信息和开发环境。Java的设计者希望给开发人员以随心所欲使用Java的自由。

动力节点 面试题 JVM

JVM相关面试题 1.JVM运行时内存结构 1.由如下图构成。Runtime Data Area有如下几个区,其中PC程序计数器、虚拟机栈和本地方法栈是线程独享的,堆和方法区是线程共享的。Classload用来加载class文件,执行引擎用来执行程序,本地方法接口调用本地方法库。 2.java stack比较简单,每一个都是一个栈帧,每个栈帧由三部分构成。局部变量区、操作数区和帧数据区。局部变量是一个以数组形式管理的内存区,一般第0位是指向自己的this引用;其他的都是基本数据类型和reference类型和returnedAddress类型。操作数区不是通过索引来访问,通过入栈出栈来访问,是临时数据的存储区域,比方说数学计算。帧数据区是保存一些指向常量池的指针,需要常量数据时就通过这个指针来访问常量池数据。

3. 共享内存区:分为permanent space、old space、From survivor、To survivor和Eden。其中premanent包括runtime constant pool和已加载的类信息和方法信息。Old space(tenured generation)包含生命周期长的存活对象。From survivor和Eden存放存活比较短的对象,To survivor是用来复制保存存活的对象。 4.JVM参数设置。 堆: -Xmx:最大堆内存,如:-Xmx512m -Xms:初始时堆内存,如:-Xms256m -XX:MaxNewSize:最大年轻区内存 -XX:NewSize:初始时年轻区内存.通常为 Xmx 的 1/3 或 1/4。新生代= Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90% -XX:MaxPermSize:最大持久带内存 -XX:PermSize:初始时持久带内存 -XX:+PrintGCDetails。打印 GC 信息 -XX:NewRatio 新生代与老年代的比例,如 – XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3 -XX:SurvivorRatio 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10 栈: -xss:设置每个线程的堆栈大小. JDK1.5+ 每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的。List集合存储元素特点? 2.对象和内存溢出 1.对象。 A.创建。首先检查指令的参数能不能在常量区找到类的符号引用,并检查这个类是否加载、解析和初始化过,如果没有就执行类的加载过程 。其次是内存分配,类加载之后就知道要分配的内存大小,分配方法 有两种,一种是指针碰撞,就是一块内存是使用过的,一块是未使用 的,用一个指针分割,新分配的内存指针就向空闲的挪动,compact 功能的虚拟机是用指针碰撞;另一种是空闲列表,就是一个列表记录

操作系统实验进程调度和内存管理java语言版本

源代码: 第一个类:divDTO publicclassdivDTO { privateintdivBase; privateintlength; privateintdivFlag; publicdivDTO(intdivBase,intlength,intdivFlag) { this.divBase=divBase; this.divFlag=divFlag; this.length=length; } publicdivDTO() { }

{ this.divBase=base; } publicintgetDivBase() { returnthis.divBase; } publicvoidsetLength(intlength) { this.length=length; } publicintgetLength() { returnthis.length; }

{ this.divFlag=flag; } publicintgetDivFalg() { returnthis.divFlag; } } 2.第二个类:PcbDTO publicclassPcbDTO { staticfinalintRunning=1; staticfinalintReady=2; staticfinalintWaiting=3; privateStringprocessName;

privateintrunTime; privateintprority; privateintprocessState; privateintbase; privateintlimit; privateintpcbFlag; publicPcbDTO(Stringname,inttime,intpro,intbase,intlimit) { this.processName=name; this.runTime=time; this.prority=pro; this.processState=0; this.limit=limit; this.base=base; } publicPcbDTO()

JAVA经典面试题:Java内存模型

JAVA经典面试题:Java内存模型 因为Java内存模型不仅是java重点要学习的技术知识,还是面试的时候经典面试题,希望引起同学们的重视,今天千锋小编就来分享一下java内存模型的相关技术知识。 不同的渠道,内存模型是不一样的,但是jvm的内存模型标准是一致的。其实java的多线程并发问题都会反映在java的内存模型上,所谓线程安全无非是要操控多个线程对某个资源的有序拜访或修改。总结java的内存模型,要解决两个首要的问题:可见性和有序性。 可见性:多个线程之间是不能相互传递数据通信的,它们之间的交流只能经过同享变量来进行。Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程同享的。当new一个目标的时分,也是被分配在主内存中,每个线程都有自己的作业内存,作业内存存储了主存的某些目标的副本,当然线程的作业内存大小是有限制的。当线程操作某个目标时,履行次序如下: (1) 从主存仿制变量到当前作业内存(read and load) (2) 履行代码,改动同享变量值(use and assign) (3) 用作业内存数据改写主存相关内容(store and write)

当一个同享变量在多个线程的作业内存中都有副本时,如果一个线程修改了这个同享变量,那么其他线程应该可以看到这个被修改后的值,这就是多线程的可见性问题。 有序性:线程在引证变量时不能直接从主内存中引证,如果线程作业内存中没有该变量,则会从主内存中复制一个副本到作业内存中,完成后线程会引证该副本。当同一线程再度引证该字段时,有可能从头从主存中获取变量副本(read-load-use),也有可能直接引证本来的副本(use),也就是说read,load,use次序可以由JVM完成体系决议。 线程不能直接为主存中字段赋值,它会将值指定给作业内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store- write),至于何时同步往昔,依据JVM完成体系决议。有该字段,则会从主内存中将该字段赋值到作业内存中,这个进程为read-load,完成后线程会引证该变量副本。 知识就财富,这句话再IT行业显示的尤其现实残酷,懂就是懂,不懂就是不懂,所以各位同学,你的努力与否与你财富直接挂钩。一起加油吧!更多java 技术经典面试题欢迎关注千锋小编。

飞加Java学习笔记_内存管理(1)

学习就要多问一些“为什么”和“怎么”,这样才有助于提高。这就是著名的5W2H 理论! 一、JAVA 内存管理机制概述 让我们先了解一下垃圾收集的工作原理。垃圾收集器的工作就是寻找那些不再被应用程序需要的对象,当它们不会再被访问或引用的时候清除它们。所以如果使用完变量后,最好将其马上置为null ,这样gc 才会认为它不会再被访问或引用。 本文将介绍Java 内存管理机制,并以int 变量和String 为例来,来讨论它们是如果使用内存的。 Java 内存分为栈(stack)与堆(heap),这两种都是由Java 自动来管理,程序员是不能通过编程来控制的。下面来介绍这两种内存: 堆(heap)内存:用于存放类的对象,如Data d1 = new Date(),d1是分配在堆内存中的,堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小。 栈(stack)内存:用于存放基本类型的变量,如int a = 5, a 是分配在栈内存中的,栈内存中的数据是可以共享。 二、JAVA 内存管理举例分析 1. Java 内存管理举例---int 变量 当在系统中声明一个int 变量时,系统做了哪些工作呢,如图1: 样例代码分析: 1. int a = 5; //新分配给5一段内存 2. int b = 6; //新分配给6一段内存 声明一个int 变量,如int age =20 将age 指向20, 不用再次分配内存分配一段内存给20,并将age 指向它 栈(stack)中有20这个值吗?

3. a = 7; //新分配给7一段内存, 存放5的那段内存将会被回收 第一行,在栈中创建一个a 的引用,然后在栈中搜索,看是否有3这个值,如果没有,就将3存在栈中,并且将a 指向3; 第二行,处理b ,如果在栈中有6这个值,那么直接让b 指向6,而不用再次分配内存;如果栈中没有6,那么需要在栈中再次开辟一段内存用于存储b 。 第三行,再处理a, 此时会在栈内存中重新检索,看有没有7这个值,如果有,那么将a 重新指向7;如果没有,则再开辟一段内存,然后将a 指向7。 2. Java 内存管理举例---String 对象 声明String 类的对象有两种方法,一种是new 一个对象,一种是直接将字符串赋给对象,下面将分别讨论两种方法的内存管理机制。 第一种方式:new ,如图2: 使用这种方式创建对象时,jvm 是不会主动把该对象放到strings pool 里面的,除非程序调用String 的intern 方法。 第二种方式:直接赋值,如图3: 样例代码分析: 1.String s1 = new String("Beijing"); 2.Stirng s2 = "Beijing"; 如String s1 = “飞加”; 则返回已有的String 对象给用 户,而不会在heap 中重新创建一 个新的String 对象jvm 则在堆(heap)中创建新的String 对象,将其引用返回给s1,同时将该引用添加至strings pool 中 在strings pool(由栈负责维护)中有“飞加”吗? Yes(有) No(无)如String s1 = new String(“飞加”); JVM 直接在堆(heap)中分配一段内存给“飞加”,并将 s1指向它。而不会管在堆(heap)中是否已经有“飞加” 图2 图3

JVM内存分配(栈堆)与JVM回收机制

Java 中的堆和栈 简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存。 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。 在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。 引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。 具体的说: 栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。 栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。 栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义: int a = 3; int b = 3; 编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b 的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。 String是一个特殊的包装类数据。可以用: String str = new String("abc"); String str = "abc"; 两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。 而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc”则直接令 str指向“abc”。 比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。 String str1 = "abc"; String str2 = "abc"; System.out.println(str1==str2); //true

相关文档
最新文档