加入收藏 | 设为首页 | 会员中心 | 我要投稿 河北网 (https://www.hebeiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长百科 > 正文

JVM 领略着实并不难!

发布时间:2019-03-12 02:11:32 所属栏目:站长百科 来源:javaspring思维导图
导读:前些天口试了阿里的演习生,问到关于Dalvik假造性能不能执行class文件,我其时的答复是不能,可是它执行的是class转换的dex文件。对口试官继承问,为什么不能执行class文件时,我却只能答复Dalvik假造机内部的优化缘故起因,却不能正确答复详细的缘故起因。着实周
副问题[/!--empirenews.page--]

前些天口试了阿里的演习生,问到关于Dalvik假造性能不能执行class文件,我其时的答复是不能,可是它执行的是class转换的dex文件。对口试官继承问,为什么不能执行class文件时,我却只能答复Dalvik假造机内部的优化缘故起因,却不能正确答复详细的缘故起因。着实周志明的这本书就有答复:Dakvik并不是一个Java假造机,它没有遵循Java假造机类型,不能执行Java的class文件,行使的是寄存器架构而不是JVM中常见的栈架构,可是它与Java又有着千丝万缕的相关,它执行的dex文件可以通过class文件转化而来。

着实在本科时代,就有打仗过《深入领略Java假造机》,可是一向以来都没去细心研读,此刻转头想想其实是认为痛惜!研一时代花了不少时刻研读,此刻筹备谋事变了,发明许多几何内容看了又忘。索性写一篇文章,把这本书的常识点做一个总结。虽然了,假如你想看较量具体的内容,可以翻看《深入领略Java假造机》。

JVM内存地区

我们在编写措施时,常常会碰着OOM(out of Memory)以及内存走漏等题目。为了停止呈现这些题目,我们起首必需对JVM的内存分别有个详细的熟悉。JVM将内存首要分别为:要领区、假造机栈、当处所法栈、堆、措施计数器。JVM运行时数据区如下:

JVM 领略着实并不难!

措施计数器

措施计数器是线程私有的地区,很好领略嘛~,每个线程虽然得有个计数器记录当前执行到谁人指令。占用的内存空间小,可以把它当作是当前列程所执行的字节码的行号指示器。假如线程在执行Java要领,这个计数器记录的是正在执行的假造机字节码指令地点;假如执行的是Native要领,这个计数器的值为空(Undefined)。此内存地区是独逐一个在Java假造机类型中没有划定任何OutOfMemoryError环境的地区。

Java假造机栈

与措施计数器一样,Java假造机栈也是线程私有的。其生命周期与线程沟通。怎样领略假造机栈呢?本质上来讲,就是个栈。内里存放的元素叫栈帧,栈帧仿佛很伟大的样子,着实它很简朴!它内里存放的是一个函数的上下文,详细存放的是执行的函数的一些数据。执行的函数必要的数据无非就是局部变量表(生涯函数内部的变量)、操纵数栈(执行引擎计较时必要),要领出口等等。

执行引擎每挪用一个函数时,就为这个函数建设一个栈帧,并插手假造机栈。换个角度领略,每个函数从挪用到执行竣事,着实是对应一个栈帧的入栈和出栈。

留意这个地区也许呈现的两种非常:一种是StackOverflowError,当前列程哀求的栈深度大于假造机所应承的深度时,会抛出这个非常。制造这种非常很简朴:将一个函数重复递归本身,最终会呈现栈溢堕落误(StackOverflowError)。另一种非常是OutOfMemoryError非常,当假造机栈可以动态扩展时(当前大部门假造机都可以),假如无法申请足够多的内存就会抛出OutOfMemoryError,怎样建造假造机栈OOM呢,参考一下代码:

  1. public void stackLeakByThread(){ 
  2. while(true){ 
  3. new Thread(){ 
  4. public void run(){ 
  5. while(true){ 
  6. }.start() 

这段代码有风险,也许会导致操纵体系假死,请审慎行使~~~

当处所法栈

当处所法栈与假造机栈所施展的浸染很相似,他们的区别在于假造机栈为执行Java代码要领处事,而当处所法栈是为Native要领处事。与假造机栈一样,当处所法栈也会抛出StackOverflowError和OutOfMemoryError非常。

Java堆

Java堆可以说是假造机中最大一块内存了。它是全部线程所共享的内存地区,险些全部的实例工具都是在这块地区中存放。虽然,睡着JIT编译器的成长,全部工具在堆上分派徐徐变得不那么“绝对”了。

Java堆是垃圾网络器打点的首要地区。因为此刻的网络器根基上回收的都是分代网络算法,全部Java堆可以细分为:新生代和晚年月。在过细分就是把新生代分为:Eden空间、From Survivor空间、To Survivor空间。当堆无法再扩展时,会抛出OutOfMemoryError非常。

要领区

要领区存放的是类信息、常量、静态变量等。要领区是各个线程共享地区,,很轻易领略,我们在写Java代码时,每个线水平可以会见统一个类的静态变量工具。因为行使反射机制的缘故起因,假造机很难展望谁人类信息不再行使,因此这块地区的接纳很难。其它,对这块地区首要是针对常量池接纳,值得留意的是JDK1.7已经把常量池转移到堆内里了。同样,当要领区无法满意内存分派需求时,会抛出OutOfMemoryError。

制造要领区内存溢出,留意,必需在JDK1.6及之前版本才会导致要领区溢出,缘故起因后头表明,执行之前,可以把假造机的参数-XXpermSize和-XX:MaxPermSize限定要领区巨细。

  1. List list =new ArrayList(); 
  2. int i =0; 
  3. while(true){ 
  4. list.add(String.valueOf(i).intern()); 

运行后会抛出java.lang.OutOfMemoryError:PermGen space非常。

表明一下,String的intern()函数浸染是假如当前的字符串在常量池中不存在,则放入到常量池中。上面的代码不绝将字符串添加到常量池,最终必定会导致内存不敷,抛出要领区的OOM。

下面表明一下,为什么必需将上面的代码在JDK1.6之前运行。我们前面提到,JDK1.7后,把常量池放入到堆空间中,这导致intern()函数的成果差异,详细怎么个差异法,且看看下面代码:

  1. String str1 =new StringBuilder("hua").append("chao").toString(); 
  2. System.out.println(str1.intern()==str1); 
  3. String str2=new StringBuilder("ja").append("va").toString(); 
  4. System.out.println(str2.intern()==str2); 

(编辑:河北网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读