Contents
  1. 1. 问过的问题
  2. 2. jvm内存模型
  3. 3. java类的生命周期
  4. 4. 类的加载器和核心类
  5. 5. 自定义类加载器
    1. 5.1. 实现自定义class文件加载路径,实现,class文件包路径的限制
    2. 5.2. 实现类的每次重新加载,实现热加载
  6. 6. tomcat的类加载模型
  7. 7. OOM的排查
  8. 8. 常用JVM异常排查手段
  9. 9. FullGC触发的情况
  10. 10. 事务的4大特性(ACID)
  11. 11. TCP与UDP区别总结:
  12. 12. TCP的三次握手和四次挥手(双方SYN、FIN、ACK)
  13. 13. TCPIP协议封装的消息格式
  14. 14. TCP阻塞控制
  15. 15. TCP重传机制
  16. 16. SQL注入的防止
  17. 17. Collection 和Collections的区别

问过的问题

JVM:

  • JVM调优:什么场景会触发FullGC,如何避免呢(Done)
  • OutOfMemory的情况如何解决(Done)
  • 线上频繁FULLGC 如何排查?何时会触发 FULLGC ,永久代如果满了,如何解决(Done)
  • JVM的类加载机制。 和Tomcat容器的类加载机制。如果一个类已经被加载了,但是做过了修改,如何重新加载?(Done)

jvm内存模型

堆区+永久代(方法区) + 栈区(不同线程不同的线程栈)

  1. 堆区的组成:老年代+新生代(Eden区:S0区:S1区=8:1:1)
  2. 栈区的组成:N个线程栈,每个线程栈由 JVM栈、本地方法栈、程序计数器组成
  3. 方法区:存储类信息、静态成员变量、常量池(字面量和符号引用),线程共享区

java类的生命周期

  1. 编译期:java文件编译成class文件的过程:涉及格式校验、变量类型校验、捕获异常校验、插入式注解处理、简化运算
  2. 运行期:类加载、连接、初始化、创建堆中对象、卸载

类的加载器和核心类

  1. 核心类加载器
  • BootstrapClassLoader 最顶层的加载类,负责加载lib下的rt.jar、resources.jar、charsets.jar和class等
  • ExtentionClassLoader 加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件
  • Application ClassLoader 也称为SystemAppClass 加载当前应用的classpath的所有类
  • 自定义ClassLoader,可以突破class文件包路径的限制,需要重写findClass()缓存查找方法制定寻找路径即可
  1. 加载的特点
  • 不同包路径下的类由不同的类加载器加载
  • jvm懒加载,根据需要去动态加载
  • 父加载器不是父类,双亲委托:自下而上,先挨个找缓存,到了顶层缓存中还没有,就开始初始化,从各自对应负责的包路径下查找,有就创建,没有给就子加载器加载
  • 加载之后存在缓存当中
  1. 加载的结果
  • 将class文件加载在内存中。
  • 将静态数据结构(数据存在于class文件的结构)转化成方法区中运行时的数据结构(数据存在于JVM时的数据结构)。
  • 在堆中生成一个代表这个类的java.lang.Class对象,作为数据访问的入口。
  1. 核心方法: loadClass、 findLoadedClass、parent.loadClass、findBootStrapClss、findClass

自定义类加载器

实现自定义class文件加载路径,实现,class文件包路径的限制

https://www.cnblogs.com/gdpuzxs/p/7044963.html

实现逻辑:写一个classloader类(构造函数里面需要传入包真实的路径),重写findClass方法,

public class MyClassLoader extends ClassLoader{
public MyClassLoader(String classpath) {
this.classpath = classpath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte [] classDate=getDate(name);
if(classDate==null){}
else{
return defineClass(name,classDate,0,classDate.length);
}
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
}
}

实现类的每次重新加载,实现热加载

  1. 本来重写 findLoadedClass()即可,直接返回null,实现热加载,但是ClassLoader把该方法设置为final了,不希望去破坏这个规则
  2. 所以直接通过重写过的findClass来实现,相当于在上面的基础上做修改,findClass的路径为当前路径,每次loadClass,直接调用findClass方法即可,虽然只能修改本地的class类
  3. findClass需要defineClass来最终把字节码文件加载进内存当中,JVM默认相同的类加载器不能加载相同全路径的类,所以每次重新加载的时候需要new一个自定义加载器,否则会报错
    String currentPath=Class.class.getClass().getResource("/").getPath()
    MyClassLoader myClassLoader=new MyClassLoader(currentPath);
    Class c=myClassLoader.findClass("com.test.Action.Test");
    MyClassLoader myClassLoader2=new MyClassLoader(currentPath);
    Class c2=myClassLoader2.findClass("com.test.Action.Test");

tomcat的类加载模型

  1. 核心加载器
  • CommonClassLoader(默认父加载器为AppClassLoader)。加载一些tomcat/lib下面的jar包,servlet-api.jar、jsp-api.jar等
  • catalinaClassLoader(默认是空,有需要的话需要自己配置)
  • sharedClassLoader(默认是空,有需要的话需要自己配置)
  • WebAppClassLoader(tomcat下 WebRoot/应用程序/WEB-INF/lib 和 class包下的类
  1. 层级结构
  • tomcat下每个应用程序都有一个独立的类加载器,WebAppClassLoader,因为不同应用程序的类不能乱加载,更不能公用啊。
  • 但是有一些通用的类,比如JUnit、Log4j类,是不同应用程序公用的类,所以有sharedClassLoader出场,可以设置路径来实现这个类加载器,从而实现不同应用程序共同加载一些通用工具类
  • 再上一层就是CommonClassLoader:下面由shardClassLoader和CatalinaClassLoader,一个是所有应用程序,一个是tomcat容器的扩展类加载器
  • 再上一层就是AppClassLoader了,就是传统的模式往上走了
  1. 加载逻辑(源码 org.apache.catalina.loader.WebappClassLoader#loadClass)
    tomcat的类加载机制是违反了双亲委托原则的:先本地缓存查找,再全局缓存查找,再系统加载,再自己加载,最后再父加载器加载
  • 先在本地缓存中查找是否已经加载过该类(clazz = findLoadedClass0(name))
  • 再查询JVM缓存中查找是否已经加载过该类( clazz = findLoadedClass(name))
  • 让系统类加载器(AppClassLoader)尝试加载该类,主要是为了防止一些基础类会被web中的类覆盖(tomcat bin下包)(clazz = system.loadClass(name))
  • web应用的类加载器将自行加载(findClass),这里也违背了双亲 (clazz = findClass(name);)
  • 最后还是加载不到的话,则委托父类加载器(Common ClassLoader)去加载。(clazz = Class.forName(name, false, parentLoader);)

OOM的排查

引发OOM的常见情况:Perm区满了,或者Heap区满了。主要是分析dump的快照,分析对象,定位到代码,如果是正常业务,就扩大机器内存,如果代码问题,优化代码。

  1. 导致OutOfMemoryError异常的常见原因有以下几种:
  • 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
  • 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
  • 代码中存在死循环或循环产生过多重复的对象实体;
  • 使用的第三方软件中的BUG;
  • 启动参数内存值设定的过小
  1. OutOfMemoryError: PermGen space
  • 问题分析: 加载了太多的类,比如第三方jar包
  • 解决方案: 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小
  1. OutOfMemoryError: Java heap space
  • 检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。
  • 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m
  1. 常见代码引起的OOM的情况
  • 检查代码中是否有死循环或递归调用。
  • 检查是否有大循环重复产生新对象实体。
  • 检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
  • 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

常用JVM异常排查手段

  1. 监控工具的使用,自带的JConsole、visualVM的使用
  • 图形化显示 堆区内存变化、线程数、CPU使用等情况
  • visualVM可以直接生成内存快照、线程快照,也可以直接帮你计算最大的20个Object
  1. 常用命令:
  • jmap (-heap 查看堆区的配置信息)
  • jstat(gcutil看即时的各个区域的变化情况、capacity查看容量情况)
  1. gc日志分析(启动的时候设置参数,生成gc日志,然后用工具分析gc日志,比如FGC的次数、YGC的次数等信息)

  2. 快照分析(可以通过工具、命令、或者启动参数配置获取到快照,然后利用工具分析)

FullGC触发的情况

  1. 老年代空间不足:
  • 真不足,新生代出来的对象进入老年代,而老年代的剩余空间不足
  • 预判不足,统计得到的Minor GC晋升到旧生代的平均大小大于旧生代的剩余空间
  • 连续不足,如果是CMS的话,即使内存剩余够。但是内存碎片太多,没有连续的内存装下原本可以装下的对象
  • 紧急不足,CMS在FullGC的时候,因为是4个阶段清楚,未完成时新垃圾产生,而剩余空间不足,也会再次出发FullGC,而且是以Serial Old单线程的形势执行。

解决方案:调优时应尽量做到让对象在Minor GC阶段被回收

  • 调大堆区的大小,默认MaxSize是总内存的1/4,初始值是1/64
  • 代码里面,尽量不要有太大的对象产生,可以用分批读取,让该对象不直接进入老年代,而是被YGC回收掉
  • 调大年轻代的大小
  • 调大存活ratio,默认是15
  1. Perm区满了:解决方案:调大Perm区的大小,或者代码中不要加载过多的class
  2. 代码调用 System.gc()。可以设置jvm参数,禁止程序调用这个方法。

事务的4大特性(ACID)

  1. 原子性:要么全部成功,要么全部失败
  2. 一致性:事务执行前和执行后必须处于一致性状态,用户A和用户B的前加起来一共是5000; 无论AB用户之间是如何相互转换的,事务结束后两个用户的钱加起来还是5000,这就是事务的一致性。
  3. 隔离性:当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不被其他事务的操作所干扰,多个并发事务之间要相互隔离。
    隔离性差会导致常见的问题:脏读取、不可重复读、幻读
  4. 持久性:一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便在数据库系统遇到故障的情况下也不会丢失事物的操作。

TCP与UDP区别总结:

http://blog.csdn.net/xiaobangkuaipao/article/details/76793702

  • TCP面向连接(如打电话要先拨号建立连接)确认信号互相通畅;UDP是无连接的,即发送数据之前不需要建立连接
  • TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达,发送有个确认的过程;UDP尽最大努力交付,即不保证可靠交付
  • Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
  • UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
  • 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  • TCP对系统资源要求较多,UDP对系统资源要求较少

TCP的三次握手和四次挥手(双方SYN、FIN、ACK)

  • 三次握手:客户端向服务端发起请求,服务端确认收到请求确认是否能接收,客户端确认能接收并反馈给服务端。通信通道建立。 socket.connect()
    A –> B, seq=x,SYN=1,A请求和服务器B进行连接,并发送请求序列号x
    B –> A, ACK=1,ack=x+1,SYN=1,seq=y, B收到并同意A的链接x请求,确认码是x+1,;然后服务器B请求和A进行连接,SYN=1.请求码是y
    A –> B, ACK=1,ack=y+1,seq=x+1;A同意B的编号为y的链接请求,并标志该次的序列号为x+1

  • 四次挥手:客户端向服务端发起断开请求,服务端确认收到请求并且把缓存的数据全部返回给客户端,服务端发送同意终止,客户端收到2次请求后确认断开并告知服务器 socket.close()
    A –> B, seq=x,FIN=1,A请求和服务器B断开连接,并发送请求序列号x
    B –> A, ACK=1,ack=x+1,seq=u, B同意seq为x的断开请求
    B –> A, FIN=1,seq=v,ack=x+1,B请求和A断开连接,请求码v,这是针对seq为x的断开连接的最终同意
    A –> B, ACK=1,ack=v+1,seq=x+1,A确认收到了B的通知,等待2*MSL,断开连接

TCPIP协议封装的消息格式

https://blog.csdn.net/hongse_zxl/article/details/50036305

  • 16位源端口号、16位目标端口号
  • 32位请求序列号(seq)
  • 32位确认序列号(ack)
  • 4位首部大小,6位预留,6位Flag ,16位窗口大小
  • 16位校验和、16位紧急指针
  • 可选项和数据

TCP阻塞控制

为了保护Server端的带宽,TCP采用了滑动窗口机制,由server动态调整窗口容量,分批确认,从而实现控流,发送方和接收方各有一个活动窗口缓存,为了准备重传。
控流方式:

  • 慢启动:启动时限制可发送包大小,然后指数增长到阈值,ack确认一个增长一些,再线性增长,防止一连接就大量包
  • Nagle算法:发送端缓存满一个ack包时再发送,避免小包
  • Cork算法:当滑动窗口值小于某值时,停止发送,一直到接收端调整到该阈值时才允许发送

TCP重传机制

  • 超时重传(超过一段时间未收到ack的话,再一定次数范围内不停的重传)
  • 快速重传 当接收方收到的数据包是不正常的序列号,那么接收方会重复把应该收到的那一条ACK重复发送,这个时候,如果发送方收到连续3条的同一个序列号的ACK,那么就会启动快速重传机制,把这个ACK对应的发送包重新发送一次。
  • 选择重传(通过报文记录信息补发丢失的包)

SQL注入的防止

  1. 尽量使用预编译语句,比如PreparedStatement,或者是成熟的持久化框架,JPA、Mybatis
  2. 必须使用原生SQL的话,比如存储过程的参数,或者Mybatis要用 $拼接的时候,需要 正则表达式 校验

Collection 和Collections的区别

  1. Collections是工具类,常用的方法,sort(List), copy(tarList,srcList),min(List)等操作
  2. Collection是接口,子类接口有 List、Set、Queue,抽象方法:isEmpty()、clear()、contains()等方法
Contents
  1. 1. 问过的问题
  2. 2. jvm内存模型
  3. 3. java类的生命周期
  4. 4. 类的加载器和核心类
  5. 5. 自定义类加载器
    1. 5.1. 实现自定义class文件加载路径,实现,class文件包路径的限制
    2. 5.2. 实现类的每次重新加载,实现热加载
  6. 6. tomcat的类加载模型
  7. 7. OOM的排查
  8. 8. 常用JVM异常排查手段
  9. 9. FullGC触发的情况
  10. 10. 事务的4大特性(ACID)
  11. 11. TCP与UDP区别总结:
  12. 12. TCP的三次握手和四次挥手(双方SYN、FIN、ACK)
  13. 13. TCPIP协议封装的消息格式
  14. 14. TCP阻塞控制
  15. 15. TCP重传机制
  16. 16. SQL注入的防止
  17. 17. Collection 和Collections的区别