笔记:类加载器、JVM逃逸分析、Mybatis缓存机制

每天学习一点小知识

1.类加载系统

1.1.类加载器:每个类加载器都有自己的内存,每个类的加载器不同,即使是同一个类,加载的字节码也不同;

    类加载器有哪些:

  • BootStrapClassLoader
  • ExtClassLoader
  • AppClassLoader
  • 自定义类加载器

1.2 类加载机制:双亲委派模型

行为特征:向上询问,向下委派;

优点:可以保证同一个类只能被同一个类加载器加载一次,保证了类体系的健壮性;

缺点:需要一些CPU资源,影响效率;且对不同项目的包名,类名相同的类,无法实现正确加载;著名的tomcat框架就打破了双亲委派机制,实现了对不同项目中,但同一个签名的两个类的加载;

1.3 类的加载过程

  1. 查找类
  2. 读取类
  3. 连接:校验->准备->解析
  4. 初始化类->主动使用/被动使用: 被动使用时是不会初始化类的!!!

类的被动使用:通过调用子类的对象,该对象来自于父类;此时两个类都会被加载,但是子类属于被动加载,不执行初始化阶段,此时子类的静态代码块也就不执行了(静态代码块的执行时机在加载过程中的初始化阶段);

1.4 类的加载方式:

1.new对象,通过构造方法加载类;

2.通过反射加载对象,例如class.forName()

3.通过ClassLoader实例的loadClass()方法来加载

这三种加载方式分为静态加载和动态加载,前两个是静态加载:如果找不到要加载的类,抛出的是NoClassDefFoundError,使用的类都是当前类加载器,即应用程序上下文加载器;第三个是动态加载:如果在运行环境中找不到要初始化的类,抛出的是ClassNotFoundException,使用的加载器是用户指定的类加载器;

class.forName() 与 classLoader.loadClass() 的主要区别:方法参数里装载的对象不一样,前者装载的对象已经初始化,而后者连接过程都还没走完,更别提初始化了

1.5  如何自定义类加载器

直接或间接地继承ClassLoader类并重写相关方法

2.接口的默认方法

JDK1.8之前,接口里的方法都是抽象的,如果要实现某个接口,就必须重写接口里的所有方法;在实际开发里,实现的接口里不一定要用到所有的方法;因此在JDK1.8之后,接口里除了抽象方法,还有默认的实现方法,这种方法实现接口的实现类里,不一定要重写,这样我们就可以按照业务的需求,来写所需要的方法,减少了无用的代码量;

3.JVM调优

逃逸分析

一种用于java堆内存使用的算法;随着技术发展,对象已经不一定要存在堆上,也有可能存在栈里,而逃逸分析就是减少java对象在堆里面的分配;

逃逸对象的定义: 当一个对象在方法内创建,又没有被外界引用,则称该对象未逃逸;这种对象如果内存较小,随着逃逸分析的开启,会把内存分配给栈上;

当对象分配在堆时,GC操作会导致STW,程序会被暂停;并且,如果对象没有进入TLAB区时,会被加锁,同样导致了效率的降低;但是对象分配在栈时,不会触发GC操作,而且对象会自行随着栈帧销毁,响应的效率会提高许多甚至几十倍;

设置逃逸分析参数: -XX:+DoEscapeAnalysis ,在JDK8里默认是打开逃逸分析的,想要关闭,把参数里的加号改为减号即可;

同步锁消除: 由于同步锁的开销太大,如果编译期发现一个对象没有发生逃逸,那么就会移除该对象的同步锁;

标量替换: 标量是指一个无法再分解的数据,例如java中的原始数据类型;相对的,还能分解的数据称为聚合量,比如java中的对象;在JIT阶段,经过逃逸分析,发现一个对象不会逃逸的话,且该对象可以被标量替换,那么可以不直接创建该对象,而是使用基本类型来替代对象,减少了开销;

4.MyBatis的缓存机制(牺牲空间,换取时间)

一级缓存:

MyBatis框架内置了一级缓存,也称为会话缓冲,即SqlSession;它会保存查询语句相同的查询结果,等到下次查一样的语句时,就会从缓冲直接拿结果,不会再去数据库查询;一级缓存默认开启,无法关闭;

当出现以下情况时,都会把会话缓存都清空:

  • sqlSession通过调用方法clearCache();
  • 当发生了数据的增,删,改时,都会清除会话缓存,即使数据并没有真的发生变化;

二级缓存:

二级缓存的应用优先级高于一级缓存,myBatis先从二级缓存查数据,没找到再去一级缓存,还没找到,才到数据库里查数据;

二级缓存也称为nameSpace缓存,是作用于某个nameSpace的,即某个mapper;二级缓存默认全局开启,但是namespace默认未开启;如果要开启namespace的二级缓存,需在某个mapper的xml文件里添加标签:<cache/>,表示当前XML中所有查询都开启了二级缓存;如果某个查询不需要缓存,在xml文件里配置useCache="false",可以关闭缓存;

当启用二级缓存,每次查询时,日志会出现Cache Hit Ratio的记录;

二级缓存的数据是存在磁盘上的,需要查询结果的数据类型实现序列化接口,如果没实现接口,程序会直接报错;

二级缓存和一级缓存一样,只要执行了任何增,删,改的写操作,都会清除缓存;

MyBatis小结:

MyBatis不管是一级还是二级缓存,只要发生了写操作,就会清除缓存;而且这种机制我们还无法改变,实际开发中很少使用到MyBatis的缓存机制;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值