内存碎片

JVM层GC调优(上)

混江龙づ霸主 提交于 2020-03-01 16:47:10
JVM内存结构简介(jdk1.8) JVM层的GC调优是生产环境上必不可少的一个环节,因为我们需要确定这个进程可以占用多少内存,以及设定一些参数的阀值。以此来优化项目的性能和提高可用性,而且这也是在面试中经常会被问到的问题。 想要进行GC调优,我们首先需要简单了解下JVM的内存结构,Java虚拟机的规范文档如下: https://docs.oracle.com/javase/specs/jvms/se8/html/index.html 在介绍JVM内存结构之前,我们需要先知道 运行时数据区 这样的一个东西,它与JVM的内存结构有着一定的关联。不过它属于是一个规范,所以与JVM内存结构是有着物理上的区别的。运行时数据区如下: 1.程序计数器(Program Count Register,简称PC Register): JVM支持多线程同时执行,每一个线程都有自己的PC Register。当每一个新线程被创建时,它都将得到它自己的PC Register。线程正在执行的方法叫做当前方法。如果执行的是Java方法,那么PC Register里存放的就是当前正在执行的指令的地址,如果是native方法(C/C++编写的方法),则是为空。此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 2.虚拟机栈(JVM Stacks): Java虚拟机栈

java 常见面试题

倖福魔咒の 提交于 2020-03-01 12:44:31
基本问题 基本数据类型和对象的区别 (1) 基本数据类型的存储原理:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的栈上的,数据本身的值就是存储在栈空间里面,Java语言里面八种数据类型是这种存储模型; (2) 引用类型的存储原理:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java堆和栈来进行这种类型的数据存储,简单地讲,“引用”(存储对象在内存堆上的地址)是存储在有序的栈上的,而对象本身的值存储在堆上的; 不论是基本数据类型还是引用类型,他们都会先在栈中分配一块内存,对于基本类型来说,这块区域包含的是基本类型的内容;而对于引用类型来说,这块区域包含的是指向真正内容的指针,真正的内容被手动的分配在堆上。 JAVA中的数据类型及其各自的特点。 分为基本类型和引用类型,基本类型有八个,数值型的有byte(1字节),short(2字节),int(4字节),long,float,double,布尔类型的bool和字符类型的char。引用类型有类,接口,数组。 JAVA面向对象的特征? 封装、继承、多态、抽象 封装:通过类来体现,将实体封装成类,其中包含属性和方法 继承:类与类之间可以继承特点,使得代码重用 多态:通过传递给父类对象引用不同的子类从而表现出不同的行为 抽象: 将一类实体的共同特性抽象出来

glibc下的内存管理

白昼怎懂夜的黑 提交于 2020-03-01 03:59:03
glibc下的内存管理 几周前我曾提到,我被项目组分配去做了一些探究linux下内存管理机制的活儿。因为我们的产品遇到了一些与之相关的“诡异”问题。这些问题以及相关情况可以概括如下: 先介绍一下相关的背景。由于我们是3D软件,所以用户经常会有“导入/导出”各种geometry的需求。而一个存储这些数据的文件,可能含有不止一个geometry,而且每个geometry中也可能存在着成千上万个面片/多边形等各种基本元素。这些元素本身都不大,但数量很多。 第一次导入geometry时,会占据大量内存(比如说吧,有1.5G)以上;在不关闭软件而进行各种“清理”操作后,内存却基本不释放;接着再次导入相同的geometry时,内存也没有明显增加;然而如果再进行一次导入操作的话,内存又会被大量占用(约1G以上)。 将以上试验,换成先导入geometry1, 然后清理场景, 再导入geometry2,此时geometry2的内存占用量,要比单独首次导入geometry2时所占用的内存量要小。 valgrind是一款在linux下经常使用检查各种内存管理问题的工具集合。我们用valgrind的memcheck组件进行过专门的内存泄露测试,并未发现明显的泄露情况。 我们的产品在mac平台上也有相应的版本。拿到mac os x上做实验,发现同样的代码,表现并不相同。其中每次清理场景后,都会有可观的内存

Java内存分配及垃圾回收

白昼怎懂夜的黑 提交于 2020-02-29 10:26:28
一:Java虚拟机数据区组成 Java虚拟机数据区有五大部分组成,分别是:方法区、堆区、虚拟机堆栈区、本地方法区、程序计数器区,这五个部分分成两组,分别是: (A)线程共享部分: 1.方法区:这个区域被各个线程共享使用,用来存储被虚拟机加载的类、常量、静态变量、即时编译后代码等信息,这个区域相对于【堆区】而言稳定很多,但仍然存在内存溢出的概率,本区会涉及到内存回收。 2.堆区:堆区是虚拟机中内存中占用最大的一部分,用来存储由各个线程运行时创建的各种非瞬时性的对象副本,因为涉及到多线程的同时使用(读取和写入),因此,这个区域是垃圾回收机制发挥主要作用的地方,也是最容易发生内存泄漏的地方,这个区域是内存管理的核心区域,内存管理的大部分功能都是围绕着这个区域的健康运行而设计的。 (B)线程独占部分: 3.虚拟机堆栈:这个区域其实就是单个线程的操作区,相当于线程这个工人的私人操作台。 4.本地方法栈:和虚拟机栈类似,只是Java虚拟机使用到的本地(非本虚拟机产生或者由其它语言产生的方法)方法提供服务的场所,类似于向其它厂商提供零件、接收其它厂商零件等等与配套厂商协作的场所。 5.程序计数器:这个区域用来记录单个线程在运行过程行号、跳转控制等等。 二、对象内存分配: 当虚拟机遇到new指令时,虚拟机会在方法区的常量池中去寻找这个类的引用标记,如果找到则进行分配内存,初始化变量等;如果没有找到

存储器管理——分配

别等时光非礼了梦想. 提交于 2020-02-29 09:05:49
连续分配是指为一个用户程序分配连续的内存空间。连续分配有单一连续存储管理和分区式储管理两种方式。 (1)单一连续存储管理 在这种管理方式中,内存被分为两个区域:系统区和用户区。应用程序装入到用户区,可使用用户区全部空间。其特点是,最简单,适用于单用户、单任务的操作系统。CP/M和DOS 2.0以下就是采用此种方式。这种方式的最大优点就是易于管理。但也存在着一些问题和不足之处,例如对要求内存空间少的程序,造成内存浪费;程序全部装入,使得很少使用的程序部分也占用—定数量的内存。 (2)分区式存储管理 为了支持多道程序系统和分时系统,支持多个程序并发执行,引入了分区式存储管理。分区式存储管理是把内存分为一些大小相等或不等的分区,操作系统占用其中一个分区,其余的分区由应用程序使用,每个应用程序占用一个或几个分区。分区式存储管理虽然可以支持并发,但难以进行内存分区的共享。 分区式存储管理引人了两个新的问题:内碎片和外碎片。前者是占用分区内未被利用的空间,后者是占用分区之间难以利用的空闲分区(通常是小空闲分区)。为实现分区式存储管理,操作系统应维护的数据结构为分区表或分区链表。表中各表项一般包括每个分区的起始地址、大小及状态(是否已分配)。 分区式存储管理常采用的一项技术就是内存紧缩(compaction):将各个占用分区向内存一端移动,然后将各个空闲分区合并成为一个空闲分区

七剑定江山之第一剑---长虹剑(jvm)

落爺英雄遲暮 提交于 2020-02-29 02:08:36
一、java旅程 萌芽前夕阶段: -1、1995年提出Oak语言,因商标已被注册,后改名为Java 萌芽阶段: 0、 1996年,正式发布1.0版本 1、 1997年,正式发布1.1版本 2、 1998年,正式发布1.2版本,java2 发芽阶段: 3、 2000年,正式发布1.3版本,java3 4、 2002年,正式发布1.4版本,java4 5、 2004年,正式发布1.5版本,java5 增长阶段: 6、 2006年12月,正式发布1.6版本,java6 7、 2011年 7月,正式发布1.7版本,java7 快速发展阶段: 8、 2014年3月18日,正式版本java8【lts】 9、 2017年9月21日,正式发布java9 10、2018年3月20日,正式发布java10 11、2018年9月25日,正式发布java11【lts】 12、2019年3月19日,正式发布java12 13、2019年9月17日,正式发布java13 二、java虚拟机架构 1、类加载系统: 负责从文件系统或者网络中加载class信息,存储到方法区的内存空间。 2、方法区: 除了类的信息外,方法区还存储运行时的常量池信息。 3、java堆: 在虚拟机启动的时候建立,几乎所有的java对象实例存放在java堆中,堆空间是所有线程共享的。 4、直接内存: java的nio库允许使用直接内存

学习笔记

纵饮孤独 提交于 2020-02-29 01:01:28
类的加载过程,类加载器是什么东西,有几种类型 jvm调优 选择jvm版本,client、server 堆区大小的指定 合理的选择收集器 小工具 jps.ext:打印jvm进程(对比linux的PS打印linux进程),如:jps -l -v jstat.exe:查看jvm运行时信息,如查看jvm进程的gc信息,100毫秒一次,循环打印20次:jstat -gc pid 100 20 jvisualvm:最欠打的运行监视和故障处理工具,可以监控内存泄漏跟踪垃圾回收,执行内存分析,cpu分析,线程分析 记得添加Visual GC插件,更加清晰 jvm参数 内存参数 -Xms:初始堆大小,包括年轻代和老年代 -Xmx:最大堆大小 -XX:NewSize=n:设置年轻代大小 -XX:NewRatio=n:年轻代和老年代的比值 -XX:SurvivorRatio=n:年轻代中Eden与两个SurvivorRatio的比值 -XX:MaxPermSize=n:设置持久代的大小 收集器参数 -XX:+UserSerialGC:设置串行收集器 -XX:+UseParallelGC:设置并行收集器 -XX:+UseParalledlOldGC:设置老年代并行收集器 -XX:+UseConcmarkSweepGC:设置老并发收集器 ...... 备注 实际中,设置堆初始内存-Xms,堆最大内存-Xmx

虚拟内存

孤人 提交于 2020-02-28 12:46:12
手动设置虚拟内存 在默认状态下,是让系统管理虚拟内存的,但是系统默认设置的管理方式通常比较保守,在自动调节时会造成页面文件不连续,而降低读写效率,工作效率就显得不高,于是经常会出现“内存不足”这样的提示,下面就让我们自已动手来设置它吧。 ①用右键点击桌面上的“我的电脑”图标,在出现的右键菜单中选“属性”选项打开“系统属性”窗口。在窗口中点击“高级”选项卡,出现高级设置的对话框 ②点击“性能”区域的“设置”按钮,在出现的“性能选项”窗口中选择“高级”选项卡,打开其对话框。 ③在该对话框中可看到关于虚拟内存的区域,点击“更改”按钮进入“虚拟内存”的设置窗口。选择一个有较大空闲容量的分区,勾选“自定义大小”前的复选框,将具体数值填入“初始大小”、“最大值”栏中,而后依次点击“设置→确定”按钮即可,最后重新启动计算机使虚拟内存设置生效。 转自:百度知道 http://baike.baidu.com/view/976.htm 虚拟内存是计算机系统 内存管理 的一种技术。它使得 应用程序 认为它拥有连续的可用的 内存 (一个连续完整的 地址空间 ),而实际上,它通常是被分隔成多个 物理内存 碎片,还有部分暂时存储在外部 磁盘存储器 上,在需要时进行 数据交换 。 目录 简介 作用 虚拟内存不足的原因 1、感染病毒 2、虚拟内存设置不当 3、系统空间不足 4、因为SYSTEM用户权限设置不当

什么技能产品经理不会提,但技术人必须懂?

断了今生、忘了曾经 提交于 2020-02-28 05:09:18
缓存是搭建高性能高并发系统的必备手段之一,通常用来解决性能瓶颈,是程序员的必备知识点,也是面试必备考点。 尽管,产品经理大概率不会关注系统性能,但程序员在实现需求的时候必须思考系统承载的并发量和用户量。缓存主要用来解决性能瓶颈的问题,一旦错误使用反而会令系统崩溃。今天,我们就通过4W的方式系统化地总结缓存相关的理论知识。 随着互联网业务的快速迭代以及用户量激增,应用架构需要不断调整甚至重构以适应这种业务的快速发展。当数据量迅速增长,业务逻辑越复杂,服务链路不断增加等等一系列问题,会导致RT过长,服务性能需要逐渐提升以满足更优的用户体验。在优化系统架构时通常的所用的两种方式scale up以及scale out,scale out就是通常所说的水平扩展,将应用服务设计成无状态性,可以方便水平扩展通过增加硬件的方式分解访问压力。而scale up则是将单个服务链路性能提升,以提升QPS以及系统的吞吐量。在追求更优的性能时,大多数业务场景是读多写少的情况,一般会通过引入缓存的方式解决。 What——什么是缓存? 关于缓存的定义,在wiki中为: a collection of data duplicating original values stored elsewhere on a computer, usually for easier access.

JVM垃圾回收详解

Deadly 提交于 2020-02-28 02:18:04
通常,我们在写java程序的时候,似乎很少关注内存分配和垃圾回收的问题。因为,这部分工作,JVM已经帮我们自动实现了。 这样看起来,好像很美好,但是任何事情都有两面性。虽然JVM会自动的进行垃圾回收,但是,如果遇到有些问题,JVM自己也处理不了呢? 因此,我们需要了解一下JVM垃圾回收是怎样运作的,这样才能在遇到问题的时候,有的放矢。所以,今天就来聊一聊JVM的垃圾回收吧。 首先,思考一下,为什么需要进行垃圾回收? 我们知道,在创建对象的时候,Java会把对象的内容放到堆中。随着时间的推移,堆中的对象肯定会越来越多,但是,堆的大小是有限制的。如果,我们不进行垃圾回收,也就是把无用的对象进行清除和回收,那么JVM将不堪重负,最终导致内存泄漏。 既然我们需要进行垃圾回收,那么,首先得知道什么是垃圾。 在垃圾收集器对堆内存进行回收前,会先判断哪些对象还在“存活”,哪些对象已经“死去”(即不可能再被任何途径使用的对象),这些“死去”的对象,就是我们需要进行回收的垃圾。 那么,通过什么方式去判定是否为垃圾呢?(即判定对象是否存活) 引用计数算法(已淘汰) 引用计数算法,是指给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1,当引用失效时,计数器的值就减1。当计数器值为0时,该对象就会被回收。 可以说,引用计数算法的实现非常简单,判定效率也很高。但是,我们忽略了一个问题