关于JVM的一些问题

1.分区具体是个什么情况?

主要是分为5大区。包括方法区、堆、虚拟机栈、本地方法栈、程序计数器。

其中方法区和堆是线程共享的数据区,虚拟机栈、本地方法栈和程序计数器是线程隔离的数据区。

程序计数器:一块较小的内存空间,作用可以看作是当前线程所执行的字节码的行号指示器(通过这个计数器的值来选取下一条需要)。注:Java虚拟机的多线程就是通过线程之间的轮流切换并且为自己分配处理器执行时间的方式实现的。

Java虚拟机栈:线程私有、生命周期与线程相同。注:每个方法被执行的时候都会去同时创建一个栈帧用于储存信息,当方法执行完毕,意味着一个线帧在虚拟机栈中完成了从入栈到出栈的过程。

本地方法栈:Java虚拟栈与本地方法栈是非常相似的,他们之间的区别就是:本地方法栈是为虚拟机使用到的Native方法服务,而Java虚拟栈是虚拟机为虚拟机执行Java方法(也就是字节码)服务。

Java堆:内存最大。是被所有的线程共享的一块区域,在这个内存区域中唯一的目的就是存放对象实例。Java堆是垃圾收集管理的主要区域,因此很多时候被称为GC堆。在java堆容易出现堆溢出,而我们通常都是将堆的最小值-xms与最大值-xmx参数设置为一样的即可避免堆自动扩展,而通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在发生内存异常的时候Dunp出当前内存的堆转储快照以便事后分析。

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

2.垃圾回收

2.1如何确定是垃圾

GC中的垃圾,指的是存在于内存中的、不会再被使用的对象。而垃圾回收就是把那些不再被使用的对象进行清除,收回占用的内存空间。

1).引用计数法

对于一个对象,有一个地方引用了他,引用计数器就+1,当引用失效的时候,引用计数器就-1。当为0的时候,就回收。

缺点:无法处理循环引用的问题;因为要涉及到引用计数器的加减,所以对性能有一定的影响。

2).根搜索算法

通过一系列的名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何的引用链连接的话,就标记。

常用的GC Roots:

虚拟机栈中的引用的对象;方法区中的类静态属性引用的对象;方法区中的常量引用的对象;本地栈中Native的引用的对象

2.2垃圾回收算法

1).标记-清除算法--Mark-Sweep

标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象。

缺点:效率问题,标记和清除过程的效率都不高;空间问题:标记清除后产生大量不连续的内存碎片--可能导致:当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不再次提前触发另一次垃圾收集动作。

2).复制算法--Copying

将原有的内存空间分为两块相同的存储空间,每次只使用一块,在垃圾回收时,将正在使用的内存块中存活对象复制到未使用的那一块内存空间中,之后清除正在使用的内存块中的所有对象,完成垃圾回收。

       现在的商业虚拟机都采用这种收集算法来回收新生代,IBM研究表明新生代中的对象98%是朝夕生死的,所以并不需要按照1:1的比例划分内存空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中的一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性地拷贝到另外一个Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1(可以通过-SurvivorRattio来配置),也就是每次新生代中可用内存空间为整个新生代容量的90%,只有10%的内存会被“浪费”。当然,98%的对象可回收只是一般场景下的数据,我们没有办法保证回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保。

优点:实现简单,内存效率高,不用考虑到碎片化的问题

缺点:可用内存被压缩到一半

3).标记-整理算法--Mark-Compact

根据老年代的特点,从而提出的这个方法。标记过程中与标记-清除一样,但是标记了之后后续步骤是让所有存活对象都向一端移动,然后清理掉端边界以外的内存。

优点:不会产生碎片

缺点:整理阶段较为占用系统内存,在标记对象多的时候,可能效率会降低。

4).分代收集算法

       主要思想是根据对象的生命周期长短特点将其进行分块,根据每块内存区间的特点,使用不同的回收算法,从而提高垃圾回收的效率。比如Java虚拟机中的堆就采用了这种方法分成了新生代和老年代。然后对于不同的代采用不同的垃圾回收算法。 新生代使用了复制算法,老年代使用了标记整理算法或者标记清理算法。

3.young gc、full gc、old gc、mix gc的概念和区别

Young GC:对象被创建时,内存的分配首先发生在年轻代(大对象可以直接被创建在年老代),大部分的对象在创建后很快就不再使用,因此很快变得不可达,于是被年轻代的GC机制清理掉(IBM的研究表明,98%的对象都是很快消亡的),这个GC机制被称为Minor GC或叫Young GC。

Full GC:对象如果在年轻代存活了足够长的时间而没有被清理掉(即在几次Young GC后存活了下来),则会被复制到年老代,年老代的空间一般比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。当年老代内存不足时,将执行Major GC,也叫 Full GC。

4.类加载机制

类加载的全过程:加载、验证、准备、解析和初始化五个阶段

加载:通过一个类的全限定名来获取定义此类的二进制字节流-->将这个字节流锁代表的静态储存结构转化为方法区的运行时数据结构-->在Java堆中生成一个代表这个类的.Class对象,作为方法区这些数据的访问入口。

验证:目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

           文件格式验证:验证版本、验证编码规格、验证常量类型......

           元数据验证:验证该类是不是有父类、是不是继承了不该继承的类、是不是抽象类,不是的话,是不是实现了接口或者父类要求实现的所有方法....

           字节码验证:验证方法体中的类型的转换是正常的、保证跳转指令不会跳转到方法体以外的字节码指令上...

           符号引用验证:符号引用中通过字符串描述的全限定名是否能找到对应的类、符号引用的类、字段和方法的访问性是否可被当前类访问。

准备:准备阶段是正式为类变量(静态变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。

解析:是虚拟机将常量池内的符号引用替换为直接引用的过程。

           类或者接口的解析

           字段解析

           类方法解析

           接口方法解析

初始化:主要工作是为静态变量赋程序设定的初值

1、使用new字节码指令创建类的实例,或者使用getstatic、putstatic读取或设置一个静态字段的值(放入常量池中的常量除外),或者调用一个静态方法的时候,对应类必须进行过初始化。

2、通过java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则要首先进行初始化。

3、当初始化一个类的时候,如果发现其父类没有进行过初始化,则首先触发父类初始化。

4、当虚拟机启动时,用户需要指定一个主类(包含main()方法的类),虚拟机会首先初始化这个类。

5、使用jdk1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、RE_invokeStatic的方法句柄,并且这个方法句柄对应的类没有进行初始化,则需要先触发其初始化。

5.类加载器

定义:虚拟机设计团队把类加载机制中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放在Java虚拟机外部去实现,而实现这个动作的代码块就称为“类加载器”。

类比较:

比较两个类是不是想等的,只有在同一个类加载器加载的前提下才有意义。

类加载器的分类:

启动类加载器(Bootstrap ClassLoader):这个类加载器是放在<JAVA_HOME >\lib 目录中,并且是虚拟机识别的类库加载到虚拟机的内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可。

扩展类加载器(Extension ClassLoader):负责加载<JAVA_HOME >\lib\ext目录中,开发者可以直接使用扩展类加载器

应用程序类加载器(Application ClassLoader):又名系统加载器,负责加载用户类路径上指定的类库,开发者可以直接使用这个加载器,默认情况下,程序就是使用的这个加载器。

双亲委派模型:

该图中展示的类加载器之间的这种层次关系,称为类加载器的双亲委派模型。

双亲委派模型除了要求顶层的启动类加载器外,别的加载器都要拥有自己的父类加载器。这里的父类加载器一般不会以继承的关系来实现,而都是使用组合的关系来复用父类加载器的代码。

双亲委派的工作过程:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类去完成,每一个层次的类加载器都是如此,因此所有的加载请求都会传送到顶层的启动类加载器中。只有当父类加载器反馈自己无法完成这个加载请求时(它的搜索范围内没有找到所需的类),子加载器才会自己尝试去加载。

双亲委派的好处:

Java类随着它的类加载器一起具备了一种带有优先级的层级关系。每个类都会传递到顶层的类加载器中去,因为该类在程序中的类加载器都是同一个,所以说就不会无法执行的情况。因为之前讨论了,如果类加载器不一样的话,那么类也就不相等,所以的话应用程序就会混乱。

破坏双亲委派模型:

第一次:在JDK1.2发布之前,也就是双亲委派模型出现之前

第二次:自身缺陷,基础类总是作为API来调用的,但是当基础类需要调用用户的代码的时候,就出现了错误。eg:JNDI服务

第三次:是由于用户对程序动态性的追求而导致的,动态性是指:代码热替换、模块热替换等

                                                                                                                                                               ----《深入理解java虚拟机》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值