JVM 内存与垃圾回收篇-9-垃圾回收算法
标记阶段:引用计数算法
垃圾标记阶段:对象存活判断
在堆里存放着几乎所有的Java对象实例,在GC执行垃圾回收之前,首先需要区分出内存中存活对象和已经死亡的对象。只有被标记为己经死亡的对象,GC才会在执行垃圾回收时释放掉其所占用的内存空间,因此这个过程称为垃圾标记阶段。
当一个对象已经不再被任何的存活对象继续引用时,就可以宣判为已经死亡
判断对象存活一般有两种方式:引用计数算法 和 可达性分析算法。
引用计数算法
引用计数算法(Reference Counting)对每个对象保存一个整型的引用计数器属性,用于记录对象被引用的情况。
对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1;当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,即表示对象A不可能再被使用,可进行回收。
优点:实现简单,垃圾对象便于辨识;判定效率高,回收没有延迟性。
缺点:
它需要单独的字段存储计数器,增加存储空间的开销
每次赋值都需要更新计数器,伴随着加法和减法操作,增加时间开销
引用计数器有一个严重的问题,即无法处理循环引用的情况。这是一条致命缺陷,导致在Java的垃圾回 ...
JVM 内存与垃圾回收篇-8-垃圾回收介绍
垃圾回收概述
WHAT 垃圾
垃圾是指在运行程序中没有任何指针指向的对象,这个对象就是需要被回收的垃圾。如果不及时对内存中的垃圾进行清理,那么,这些垃圾对象所占的内存空间会一直保留到应用程序结束,被保留的空间无法被其他对象使用,甚至可能导致内存溢出。
WHY GC
对于高级语言来说,一个基本认知是如果不进行垃圾回收,内存迟早都会被消耗完
除了释放没用的对象,垃圾回收也可以清除内存里的记录碎片。碎片整理将所占用的堆内存移到堆的一端,以便JVM将整理出的内存分配给新的对象
随着应用程序所应付的业务越来越庞大、复杂,用户越来越多,没有 GC 就不能保证应用程序的正常进行。而经常造成 STW 的 GC 又跟不上实际的需求,所以才会不断地尝试对 GC 进行优化
Java垃圾回收机制
自动内存管理机制,无需开发人员手动参与内存的分配与回收,降低内存泄漏和内存溢出的风险
垃圾回收器可以对年轻代回收,也可以对老年代回收,甚至是全堆和方法区的回收,其中 Java 堆是垃圾收集器的工作重点。
频繁收集 Young 区
较少收集 Old 区
基本不动 Perm 区
垃圾回收相关概念S ...
MySQL高级篇-10-索引优化与查询优化
索引失效案例MySQL中提高性能的一个最有效的方式是对数据表设计合理的索引。索引提供了高效访问数据的方法,并且加快查询的速度,因此索引对查询的速度有着至关重要的影响。
使用索引可以快速地定位表中的某条记录,从而提高数据库查询的速度,提高数据库的性能。
如果查询时没有使用索引,查询语句就会扫描表中的所有记录。在数据量大的情况下,这样查询的速度会很慢。
大多数情况下都(默认)采用B+树来构建索引。只是空间列类型的索引使用R-树,并且MEMORY表还支持hast索引。其实,用不用索引,最终都是优化器说了算。优化器是基于cost开销(CostBaseOptimizer),它不是基于规则(Rule-BasedOptimizer),也不是基于语义。另外,SQL语句是否使用索引,跟数据库版本、数据量、数据选择度都有关系。
全值匹配我最爱系统中经常出现的SQL语句如下:
1EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age=30;
1EXPLAIN SELECT SQL_NO_CACHE * FROM student WHERE age=30 ...
算法提升-2-KMP
引入问题
给定两个字符串str和match,长度为 $N$ 和 $M$ 。如果字符串str中含有子串match,返回match在str中开始位置。
如果match的长度大于str长度( $M>N$ ),str必然不会含有match,可直接返回-1。但如果 $N≥M$ ,要求算法复杂度为 $O(M)$
next数组next数组含义next[i] 的含义是在 match[i] 之前的字符串 match[0..i-1] 中,必须以 match[i-1] 结尾的 后缀子串 与必须以match[0]开头的 前缀子串 最大匹配长度
后缀字符不能包含match[0],即整个后缀不能是本身
前缀字符不能包含match[i-1],即整个前缀不能是本身
求解next数组match[0] :他之前没有字符,next[0] 规定为 -1
match[1] :next数组定义要求任何子串后缀不能包含第一个字符,故 match[1] 之前的字符串只有长度为0的后缀字符串,next[1] 规定为0
match[i]
1.从左至右依次求解next,求解 next[i] 时,next[i-1] ...
MySQL高级篇-9-性能分析工具的使用
数据库服务器的优化步骤
首先在S1部分,需要观察服务器的状态是否存在周期性的波动。如果存在周期性波动,有可能是周期性节点的原因,比如双十一、促销活动等。这样的话,可以通过A1加缓存,或者更改缓存失效策略。
如果缓存策略没有解决,或者不是周期性波动的原因,就需要进一步分析查询延迟和卡顿的原因。接下来进入S2这一步,需要开启慢查询。慢查询可以定位执行慢的SQL语句。可以通过设置long_query_time参数定义“慢””的阈值,如果SQL执行时间超过long_query_time,则会认为是慢查询。当收集上来这些慢查询之后就可以通过分析工具对慢查询日志进行分析。
在S3这一步骤中就知道了执行慢的SQL,就可以针对性地用EXPLAIN查看对应SQL语句的执行计划,或者使用show profile查看SQL中每一个步骤的时间成本,了解SQL查询慢是因为执行时间长,还是等待时间长。
如果是SQL等待时间长,我们进入A2步骤。在这一步骤中,可以调优服务器的参数,比如适当增加数据库缓冲池等。
如果是SQL执行时间长,就进入A3步骤,这一步中我们需要考虑是索引设计的问题?还是查询关联的数据表过多? ...
JUC-6-volatile与JMM
volatile
被volatile修饰的变量特点
可见性
有序性
volatile内存语义
当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中
当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,重新回到主内存中读取最新共享变量
volatile写的内存语义是直接刷新到主内存中,读的内存语义是直接从主内存中读取。
内存屏障内存屏障(内存栅栏,屏障指令等),是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作,避免代码重排序。内存屏障其实就是一种JVM指令,Java内存模型的重排规则会要求Java编译器在生成JVM指令时插入特定的内存屏障指令,通过这些内存屏障指令,volatie实现了Java内存模型中的可见性和有序性(禁重排),但volatile无法保证原子性。
内存屏障之前的所有写操作都要回写到主内存,内存屏障之后的所有读操作都能获得内存屏障之前的所有写操作的最新结果(实现了可见性)。写屏障(Store Memor ...









