首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

详解java之JVM内存机制

Class Loader 当你编译一个.java 源文件时,它会被编译成以.class 结尾的 byte code 文件。当你在程序中尝试使用这个类文件时,类文件就会把它加载进主内存上。...在 Intialization 阶段,变量被赋值为 true。 注意:JVM 是多线程的。会发生多线程在同一时间都试图去对同一个类做初始化的情况。这会导致并发连接问题。...方法区是在虚拟机启动的时候被创建的,每个 JVM 只有一个方法区。 Heap Area 所有的对象及它们响应的实例变量都存储在这。这是为所有类实例和数组分配内存的运行时数据区域。...如果在线程中需要处理所需要空间比可用栈空间更大,JVM 就会抛出 StackOverflowError。 对于每次方法调用,在栈内存中所创建的 entry 被叫做 Stack Frame。...StackOverflowError-如果 JVM 在处理线程时创建新的堆栈帧时耗尽空间,就会发生这种情况。 总结 本文我们讨论_Java Virtual Machine_的结构和它们多样的组件。

27010

谈谈JVM内存区域的划分,哪些区域可能发生 OutOfMemoryError?

在 JVM 规范中,每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。...每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用。...前面谈程序计数器时,提到了当前方法;同理,在一个时间点,对应的只会有一个活动的栈帧,通常叫作当前帧,方法所在的类叫作当前类。...第三,堆(Heap),它是 Java 内存管理的核心区域,用来放置 Java 对象实例,几乎所有创建的 Java 对象实例都是被直接分配在堆上。...类似这种情况,JVM 实际会抛出StackOverFlowError;当然,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出 OutOfMemoryError。

77100
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    JDK1.8-Java虚拟机运行时数据区域和HotSpot虚拟机的内存模型

    二: 如果栈内存可以扩展并尝试扩展时可用的内存不足, 或者创建新线程并为其分配栈内存时可能的内存不足, 会抛出OutOfMemoryError 下面先演示第一个StackOverflowError异常...比如说在多态的情况下, 一个接口对应的实现类不同, 具体的实现方法也不同, 虚拟机只有在程序运行的过程中才知道要创建哪些对象, 这部分内存的分配和释放都是动态的, 垃圾收集器关注的也是这部分的内容....我们知道对象是存储在堆内存中的, 从字面上理解新生代就是新创建的对象区域, 老年代就是使用多次生命周期长的对象区域....具体操作是这样的: 程序运行时, 用Eden区和一个Survivor区A存放新创建的对象....元数据区和永久代有着本质的区别, 永久代属于虚拟机内存的一部分, 也就是说当在操作系统中启动虚拟机进程时为它分配了一块内存, 而虚拟机为永久代分配内存时用的是它自己分配得的内存.

    60920

    深入浅出JVM(二)之运行时数据区和内存溢出异常

    )这是在类加载时验证阶段的字节码验证过程需要保证的动态连接动态连接:栈帧中指向运行时常量池所属方法的引用静态解析与动态连接符号引用转换为直接引用有两种方式静态解析:在类加载时解析阶段将符号引用解析为直接引用动态连接...,又递归调用频繁的创建栈帧,很快就会超过栈内存,从而导致StackOverflowError测试OOM在我们经常使用的hotSpot虚拟机中是不支持栈扩展的所以线程运行时不会因为扩展栈而导致OOM,只有可能是创建线程无法申请到足够内存而导致...堆的目的就是为了存放对象实例数据生命周期因为大部分对象实例都是存放在堆中,所以JVM启动时,堆就创建了 (注意这里的大部分,不是所有对象都存储在堆中)又因为线程都要去用对象,因此堆是线程共享的堆内存堆的内存在物理上是可以不连续的...,通过一个在Java堆中DirectByteBuffer的对象作为这块物理内存的引用进行IO操作 避免在Java堆中和本地物理内存堆中来回copy数据直接内存分配不受Java堆大小的影响,如果忽略掉直接内存...大部分对象都存储在堆中,堆内存划分为新生代(伊甸园区、幸存0区、1区)、老年代、元空间(直接内存),对象生命周期长短不一,新生代与老年代GC时使用的算法也不同;当堆内存不足,无法给新对象分配内存时,发生内存溢出异常

    24731

    上周面了百度,问的很细~

    同时,它会向其他 CPU 广播一个“无效消息”,使得其他 CPU 将自己缓存中对应的数据状态转变为I(无效)状态,从而在下次访问这个数据时能够从主存储器或其他 CPU 的缓存中重新获取正确的数据。...堆内存溢出:当创建大量线程时,每个线程可能会创建和管理多个对象,这些对象都存储在堆中,当对象超过 JVM 配置的最大堆内存时(通过 -Xmx 参数设置),可能会导致 java.lang.OutOfMemoryError...方法区溢出: 在多线程应用中,当线程中的代码涉及到动态类加载(例如使用线程上下文类加载器加载不同的类)时,可能会导致方法区(或其替代品 Metaspace)内存的快速增长。...说说创建一个对象的过程?创建一个对象的过程如下:类加载检查:当通过 new 关键字创建一个对象时,JVM 首先会检查该对象的类是否已经被加载并初始化了。...构造方法执行完成后,一个完全初始化且可直接使用的对象才算创建成功。注意:对象创建过程和类加载机制(加载、验证、准备、解析、初始化)略有不同。

    15610

    针对高级前端的8个级JavaScript面试问题

    构造函数用于在 JavaScript 中创建对象。当您定义一个构造函数时,还可以将属性和方法附加到其 prototype 属性上。这些属性和方法然后变得可以被该构造函数创建的所有对象实例访问。...每个这样的对象都有一个原型,该原型作为对另一个对象的引用。__proto__ 属性简单地是对这个原型对象的引用。 当你试图访问对象上的一个属性或方法时,JavaScript 会进行查找过程来找到它。...当我们定义了foo函数,它被赋予了访问自己的局部作用域和全局作用域的权限。这一特性在我们无论在哪里调用foo函数时都是一致的,无论是在bar函数内部还是在其他模块中运行。...现在,当foo试图访问变量a时,它首先会在自己的局部作用域内进行搜索。由于没有找到a,它会扩大搜索范围到bar函数的作用域。果然,那里存在一个值为3的a。因此,控制台语句将输出3。...这是一个有趣的问题,测试你是否了解对象的强制类型转换。 在像字符串连接或算术运算这样的场景中与对象一起工作时,这种转换至关重要。

    21830

    针对高级前端的8个级JavaScript面试问题

    构造函数用于在 JavaScript 中创建对象。当您定义一个构造函数时,还可以将属性和方法附加到其 prototype 属性上。这些属性和方法然后变得可以被该构造函数创建的所有对象实例访问。...每个这样的对象都有一个原型,该原型作为对另一个对象的引用。__proto__ 属性简单地是对这个原型对象的引用。 当你试图访问对象上的一个属性或方法时,JavaScript 会进行查找过程来找到它。...当我们定义了foo函数,它被赋予了访问自己的局部作用域和全局作用域的权限。这一特性在我们无论在哪里调用foo函数时都是一致的,无论是在bar函数内部还是在其他模块中运行。...现在,当foo试图访问变量a时,它首先会在自己的局部作用域内进行搜索。由于没有找到a,它会扩大搜索范围到bar函数的作用域。果然,那里存在一个值为3的a。因此,控制台语句将输出3。...这是一个有趣的问题,测试你是否了解对象的强制类型转换。 在像字符串连接或算术运算这样的场景中与对象一起工作时,这种转换至关重要。

    18710

    深入了解Android的Looper

    Handler和Looper Handler我们都知道,它需要和Looper绑定,当Handler在主线程创建,则会默认绑定主线程的Looper,当是在子线程创建,则需要在Handler的构造方法里传入子线程的...()方法,构造了一个Looper对象,并保存在sThreadLocal中。...时,就会从 sThreadLocal 中获取。...当然这里面还有其他几个细节,我们留着下次继续分析,比如 1 既然loop()是个无限循环,它为什么不会造成资源无限消耗 2 ThreadLocal是怎么做到当前线程只能获取到它自己的Looper的 总结...Looper的原理可以总结如下, · 每个线程都可以创建一个Looper,它会保存在当前线程对应的ThreadLocal里 · Handler需要绑定对应线程的Looper对象 · 线程在创建完Looper

    35410

    Atom飞行手册翻译: 2.7 ~ 2.10

    面板被分割后,你可以使用cmd-k cmd-arrow快捷键在它们之间移动焦点,其中“arrow”是焦点要移动的方向。 每个面板都有它自己的“条目”或文件,它们由标签页来表示。...你可以通过拖动文件,并把它放到想要放进去的面板中,来在面板之间移动文件。 要关闭一个面板,按下cmd-w来关闭它的所有编辑器,然后再按下cmd-w几次来关闭面板。...你可以在设置视图中,将面板设置为没有东西的时候自动关闭。 语法 一个缓冲区中的“语法”,是Atom所认为的,文件内容的语言类型。语法类型可以是Java或者Markdown。...当我们在“Snippets”中创建代码段的时候,我们已经看到过它了。 如果你加载了一个文件,Atom会做一些工作来试图识别出文件的类型。...如果你加载了一个文件,并且Atom不能判断文件的语法,它会默认为纯文本(Plain Text),这是最简单的类型。

    43220

    一问带你彻底了解JVM-Java内存区域详解

    、long)、对象引用(reference,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其它与此对象相关的位置)、returnAddress 类型 这些数据类型在局部变量表中的存储空间以局部变量槽...,在Java虚拟机启动时创建。...heap space:假如在创建新对象时,堆的内存空间不足以存放该新对象时,就会发生次错误。...// 在堆中创建字符串对象"paidaxing" // 将字符串对象"paidaxing"的引用保存在字符串常量池中 String a = "paidaxing"; // 直接返回字符串常量池中字符串对象...如图所示: 问题来了为什么JDK1.7要将字符串常量池移到堆中呢?

    45610

    程序员进阶系列:OOM 都搞不定,还敢妄称自己Java高级攻城狮?

    [] bytes = new byte[20 * 1024 * 1024]; System.out.println(bytes); } } 理论且不谈,直接抛代码,代码很简单,创建一个字节数组对象...(虚妄的单身狗生活:一直创建女朋友对象。)...当出现 java.lang.OutOfMemoryError: PermGen space 异常时,要能够知道可能是由于太多的类或者太大的类被加载到方法区导致的。...因为当 JVM 向操作系统请求创建一个新线程时,然而操作系统也无法创建新的 native 线程时就会抛出 Unable to create new native thread 错误。...当你编写的 Java 程序试图要分配大于 Java 虚拟机可以支持的数组时就会报 OOM,Java 对应用程序可以分配的最大数组大小有限制,不同平台限制有所不同。

    52110

    架构师成长之路:如何保证消息队列的高可用

    在 JVM 规范中,每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。...每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用。...前面谈程序计数器时,提到了当前方法;同理,在一个时间点,对应的只会有一个活动的栈帧,通常叫作当前帧,方法所在的类叫作当前类。...类似这种情况,JVM 实际会抛出StackOverFlowError;当然,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出OutOfMemoryError。...标记 - 整理(Mark-Compact),类似于标记 - 清除,但为避免内存碎片化,它会在清理过程中将对象移动,以确保移动后的对象占用连续的内存空间。

    46010

    【Python环境】12道 Python面试题总结

    当使用del对对象显示销毁或者引用超出作用于或者被重新赋值时,该对象的引用计数就会减少。 可以使用sys.getrefcount()函数来获取对象的当前引用计数。...浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数...为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变? 这个答案的关键是,在 Python 中,类变量在内部是作为字典处理的。...因此,在父类中设置 x = 1 会使得类变量 X 在引用该类和其任何子类中的值为 1。这就是因为第一个 print 语句的输出是 1 1 1。...认为 list 的参数会在 extendList 每次被调用的时候会被设置成它的默认值 []。 尽管如此,实际发生的事情是,新的默认列表仅仅只在函数被定义时创建一次。

    1K50

    【JAVA】JVM 内存区域的划分

    在 JVM 规范中,每个线程都有它自己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。...每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用。...前面谈程序计数器时,提到了当前方法;同理,在一个时间点,对应的只会有一个活动的栈帧,通常叫作当前帧,方法所在的类叫作当前类。...在 java.nio.BIts.reserveMemory() 方法中,我们能清楚的看到,System.gc() 会被调用,以清理空间,这也是为什么在大量使用 NIO 的 Direct Buffer 之类时...类似这种情况,JVM 实际会抛出 StackOverFlowError;当然,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出 OutOfMemoryError。

    24730

    Java基础知识:JVM内存结构

    ; 虚拟机栈:线程私有的,每个方法执行的时候都会创建一个栈帧,用于存储局部变量表、操作数、动态链接和方法返回等信息,当线程请求的栈深度超过了虚拟机允许的最大深度时,就会抛出StackOverFlowError...每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方法调用,栈是线程私有的 对于栈来说不存在垃圾回收问题, 不需要GC,但是可能存在OOM...java.lang.OutOfMemoryError: Java heap space:假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发此错误。...图解对象分配 我们创建的对象,一般都是存放在 Eden 区的,当我们 Eden 区满了后,就会触发 GC 操作,一般被称为 YGC / Minor GC 操作 当我们进行一次垃圾收集后,红色的对象将会被回收...多个线程同时加载同一个类时,只能有一个线程能加载该类,其他线程只能等等待该线程加载完毕,然后直接使用该类,即类只能加载一次。

    74430

    12道 Python面试题总结

    当使用del对对象显示销毁或者引用超出作用于或者被重新赋值时,该对象的引用计数就会减少。 可以使用sys.getrefcount()函数来获取对象的当前引用计数。...浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数...为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变? 这个答案的关键是,在 Python 中,类变量在内部是作为字典处理的。...因此,在父类中设置 x = 1 会使得类变量 X 在引用该类和其任何子类中的值为 1。这就是因为第一个 print 语句的输出是 1 1 1。...认为 list 的参数会在 extendList 每次被调用的时候会被设置成它的默认值 []。 尽管如此,实际发生的事情是,新的默认列表仅仅只在函数被定义时创建一次。

    1.5K90

    兄dei,你被代码死循环坑了吗?

    内存使用率飙升:如果代码出现死循环时,循环体内有大量创建对象的逻辑,垃圾回收器无法及时回收,会导致内存使用率飙升。同时,如果垃圾回收器频繁回收对象,也会造成cpu使用率飙升问题。...3.类中使用自己的对象 有时候,在某个类中把自己的对象定义成成员变量,不知道你有没有这样做过。 有些可能会很诧异,为什么要这么做。...不断创建ServiceA对象,但一直都无法成功,最后会报java.lang.StackOverflowError栈溢出。当栈深度超过虚拟机分配给线程的栈大小时就会出现此错误。 为什么会出现这个问题?...因为程序在实例化ServiceA对象时,要先实例化它的成员变量serviceA,但是它的成员变量serviceA,又需要实例化它自己的成员变量serviceA,如此一层层实例化下去,最终也没能实例化。...使用Proxy创建代理类,指定被代理类的相关信息 这样在调用proxy的add方式时,会自动调用before和after方法,实现了动态代理的效果,是不是很酷?

    2.2K20

    创建子类对象时,父类构造函数中调用被子类重写的方法为什么调用的是子类的方法?

    public static void main(String[] args) { A a = new A(); B b = new B(); } } 问题:为什么创建...A对象的时候父类会调用子类方法?...但是:创建B对象父类会调用父类的方法? 答案: 当子类被加载到内存方法区后,会继续加载父类到内存中。...如果,子类重写了父类的方法,子类的方法引用会指向子类的方法,否则子类的方法引用会指向父类的方法引用。 如果子类重载了父类方法,则子类重载方法引用还指向子类方法。...如果子类方法没有重写也没有重载父类方法,则方法引用会指向父类方法。 当子类对象创建时,会先行调用父类的构造方法(构造方法也是方法),虚拟机会在子类方法区寻找该方法并运行。

    6.3K10

    几种常见的Runtime Exception

    应该声明方法抛出异常还是在方法中捕获异常?原则:捕捉并处理哪些知道如何处理的异常,而传递哪些不知道如何处理的异常。 再次抛出异常 ①为什么要再次抛出异常?...java.lang.ClassFormatError 类格式错误。当Java虚拟机试图从一个文件中读取Java类,而检测到该文件的内容不符合类的有效格式时抛出。...当可用内存不足以让Java虚拟机分配给一个对象时抛出该错误。 java.lang.StackOverflowError 堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出时抛出该错误。...当应用试图通过反射方式创建某个类的实例、访问该类属性、调用该类方法,而当时又无法访问类的、属性的、方法的或构造方法的定义时抛出该异常。...当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常。 java.lang.InterruptedException 被中止异常。

    1.2K20

    浅析 SpringMVC 中返回对象的循环引用问题

    @RestController、@ResponseBody 等注解是我们在写 Web 应用时打交道最多的注解了,我们经常有这样的需求:返回一个对象给前端,SpringMVC 帮助我们序列化成 JSON...StackOverFlow 问题剖析 不难理解这中间发生了什么,从堆栈和常识中都应当了解到一个事实,SpringMVC 默认使用了 jackson 作为 HttpMessageConverter,这样当我们返回对象时...,会经过 jackson 的 serializer 序列化成 json 串,而另一个事实便是 jackson 是无法解析 java 中的循环引用的,套娃式的解析,最终导致了 StackOverFlowError...这样的标识,解决了循环引用的问题,如果继续使用 fastjson 反序列化,依旧可以解析成同一对象,其实我在之前的文章中已经介绍过这一特性了《gson 替换 fastjson 引发的线上问题分析》。...问题思考 值得一提的是,为什么一般标准的 JSON 类库并没有如此关注循环引用的问题呢?

    6K30
    领券