一、JVM调优策略
(1)不要手动设置新生代和老年代的大小,只要设置整个堆的大小
G1收集器在运行过程中,会自己调整新生代和老年代的大小其实是通过adapt代的大小来调整对象晋升的速度和年龄,从而达到为收集器设置的暂停时间目标如果手动设置了大小就意味着放弃了G1的自动调优
(2)不断调优暂停时间目标
上般情况下这个值设置到100ms或者2oms都是可以的(不同情况下会不一样),但如果设置成5ems 就不太合理。暂停时间设置的太短,就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。暂停时间只是一个目标,并不能总是得到页足。
(3)使用-XX:ConcGCThreads=n来增加标记线程的数量
IHOP如果阀值设置过高,可能会遇到转移失败的风险,比如对象进行转移时空间不足。如果阀值设置过低,就会使标记周期运行过于频繁,并且有可能混合收集期回收不到空间。IHOP值如果设置合理,但是在并发周期时间过长时,可以尝试增加并发线程数,调高ConcGCThreadso
(4)MixedGC调优
(5)适当增加堆内存大小
(6)不正常的Full GC
有时候会发现系统刚刚启动的时候,就会发生一次Full GC,但是老年代空间比较充足,一般是由Netaspace区域引起的。可以通过MetaspaceSize适当增加其大家,比如256M。
二、什么是字节码?采用字节码的好处是什么?
java中的编译器和解释器:
Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序干个的共同的接口。
编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展名为.class的文件),它不面向任何特定的处理器,只面向虚拟机。
每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码然后在特定的机器上运行。
这也就是解释了Java的编译与解释并存的特点。
Java源代码-->编译器--->jyvm可执行的Java字节码(即虚拟指令)--->jvm--->jvm中解释器---->机器可执行的二进制机器码---->程序运行。
采用字节码的好处:
Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。
三、描述一下Spring Bean的生命周期?
1、解析类得到BeanDefinition
2、如果有多个构造方法,则要推断构造方法3、确定好构造方法后,进行实例化得到一个对象
4、对对象中的加了@Autowired注解的属性进行属性填充+
5、回调Aware方法,比如BeanNameAware,BeanFactoryAware
6、调用BeanPostProcessor的初始化前的方法
7、调用初始化方法
8、调用BeanPostProcessor的初始化后的方法,在这里会进行AOP
9、如果当前创建的bean是单例的则会把bean放入单例池
10、使用bean
11、Spring容器关闭时调用DisposableBean中destory()方法
四、Tomcat如何进行优化?
对于Tomcat调优,可以从两个方面来进行调整:内存和线程。
首先启动Tomcat,实际上就是启动了一个JVM,所以可以按JVM调优的方式来进行调整,从而达到Tomcat优化的目的。另外Tomcat中设计了一些缓存区,比如appReadBufSize、bufferPoolSize等缓存区来提高吞吐量。
还可以调整Tomcat的线程,比如调整minSpareThreads参数来改变Tomcat空闲时的线程数,调整maxThreads参数来设置Tomcat处理连接的最大线程数。并且还可以调整IO模型,比如使用NIO、APR这种相比于BIO更加高效的IO模型。
五、JVM中哪些可以作为gc root
什么是gc root,JNM在进行垃圾回收时,需要找到“垃圾”对象,也就是没有被引用的对象,但是直接找“垃圾”对象是比较耗时的,所以反过来,先找“非垃圾”对象,也就是正常对象,那么就需要从某些“根”开始去找,根据这些“根”的引用路径找到正常对象而这些“根”有一个特征,就是它只会引用其他对象,而不会被其他对象引用,例如:栈中的本地变量、方法区中的静态变量、本地方法栈中的变量、正在运行的线程等可以作为gc root。
六、Spring容器启动流程是怎样的
1.在创建Spring容器,也就是启动Spring时:
2.首先会进行扫描,扫描得到所有的BeanDefinition对象,并存在一个Map中
3.然后筛选出非懒加载的单例BeanDefinition进行创建Bean,对于多例Bean不需要在启动过程中去进行创建,对于多例Bean会在每次获取Bean时利用BeanDefinition去创建
4.利用BeanDefinition创建Bean就是Bean的创建生命周期,这期间包括了合并BeanDefinition、推断构造方法、实例化、属性填充、初始化前、初始化、初始化后等步骤,其中AOP就是发生在初始化后这一步骤中
5.单例Bean创建完了之后,Spring会发布一个容器启动事件
6. Spring启动结束
7.在源码中会更复杂,比如源码中会提供一些模板方法,让子类来实现,比如源码中还涉及到一些BeanFactoryPostProcessor和BeanPostProcessor的注册,Spring的扫描就是通过BenaFactoryPostProcessor来实现的,依赖注入就是通过BeanPostProcessor来实现的
8.在Spring启动过程中还会去处理@Import等注解
七、Mysql慢查询该如何优化?
1.检查是否走了索引,如果没有则优化SQL利用索引
2.检查所利用的索引,是否是最优索引
3.检查所查字段是否都是必须的,是否查询了过多字段,查出了多余数据
4.检查表中数据是否过多,是否应该进行分库分表了
5.检查数据库实例所在机器的性能配置,是否太低,是否可以适当增加资源