java面试题集合

jvm篇

 

javaSource:java源代码,java类

javaClass:字节码,class类

1.java虚拟机栈内存创建main方法主线程,程序入口,java 虚拟机发现没有见过的类,触发 类加载子系统(把类所有的原始信息,加载到内存中(方法区)包含类名、方法名、成员变量、引用其他类的名字)

2.加载一个类完成后,碰到new一个对象的时候,new的对象信息存储到heap堆中(一个对象有多少成员变量,需要多少个字节多存储在堆中),而局部变量、方法参数占用的是栈内存。

3.main主线程可能被cpu切换到其他线程,使用 程序计数器,记住main主线程执行到哪行代码。而线程占用的都是栈内存。

4.GC垃圾回收被弃用的java对象

5.解释器把java字节码转换成机器码,能被cpu所使用。因为这个解释器所以java可以使用于跨平台

6.对于反复调用的代码,称之为热点代码,对于这种热点代码,使用JIT及时编译器,直接去缓存中找到相应的机器码,直接交给cpu执行。

7.程序计数器、栈内存 是线程私有的。 堆内存、方法区,是线程共享的。

8.程序计数器不会内存溢出; OutOfMemoryError溢出:①对象创建过多,一直没被GC回收②方法区内存溢出,加载的类越来越多,spring框架在运行期间动态产生新的类③ 创建线程越来越多,

  长时间运行不销毁,每个线程默认最多1M的栈内存

  StackOverflowError溢出:单独的线程内方法调用次数过多(例如递归调用,无线循环下去),超过1M之后,就死翘翘了

9.方法区(物理内存上其实也是堆内存的一部分):这只是定义一块内存的名称、永久代(1.8之前)、元空间(Metaspce1.8之后)是对方法区的具体实现,现在都说叫做元空间。

10.类加载器被回收之后元空间内存才会释放(系统的类加载器一般不会被释放的....)

11.jvm参数解释:(堆内存)-Xmx 最大内存 -Xms 最小内存  -Xmn 新生代占用内存(老年代占用内存=最小内存-新生代内存)

方法区内(新生代和老年代占用内存关系如下图),其中new 是新生代,新生代又包括伊甸园区、from、to区,其中from=to的内存1:1关系

eden区和from区的比例关系使用参数设置就是 -XXSurvivorRatio =8  默认是8:1

-XXNewRatio=2 新生代和老年代的内存比例,默认是2:1

服务器一般设置-Xms、-Xmx 相等以避免在每次 GC 后调整堆的大小

 

 

 

12.GC算法

  标记:找到还在使用的对象,加上标记(根对象,一定不能被回收的,正在使用的对象和被引用的对象,静态变量),未标记的稍后会清除

  ①标记清除(已经弃用):两个阶段,第一阶段先标记,第二阶段直接清除,缺点是被释放的对象内存不是连续的,会有很多不连续内存,当存入较大的对象内存(数组,数组需要连续内存),还是会显示内存不够用

  ②标记整理:在标记清除的方法上面进行改进,在标记清除的前两个阶段多了一个整理阶段,把存活的对象,向一端靠拢,释放连续内存。缺点就是比较耗费性能,因为要移动对象,所以需要重新计算对象内存地址,还需要进行对象的复制,等等一系列操作。(老年代)

  ③标记复制:适用新生代,不适用老年代,新生代存活对象从from区复制到to区,然后直接清除from区的对象,非常快捷,但是占用内存较高

13.GC概述

  GC的存在就是为了释放内存,减少内存碎片,速度也会提升;而且是自动释放,减少程序员的工作量,

  GC回收的是堆内存,收回的对象使用的是可达性分析算法和三色标记法标记存活对象 ,回收未标记的对象

  常用GC:ParallelGC (高并发,吞吐量大的很多计算的使用这个;新生代使用MinorGC ,老年代使用FullGC )、ConcMarkSweepGC(老年代并发标记,注重响应时间),G1 GC()

  GC的回收规模 (小规模 常用新生代中)MinorGC (中规模处于二者之间,G1(Gone)收集器特有)MixedGC (大规模GC 堆内存占用85%左右发生,新生代+老年代全部回收)FullGC 

14. 新生代GC回收

  伊甸园区和幸存区(from+to)合称新生代,当伊甸园或者幸存区内存不足的时候,会采用标记复制法,清除对象,把存活的对象存储到幸存区to区中。幸存区的from区和to区每次清理后都会交换位置,重新定义from和to区

  当幸存区的对象熬过几次清理之后(最多15次),这些对象会晋升到老年代(幸存区不够了,或者大对象,会直接晋升到老年代)

15.三色标记

  黑色:已经标记

  灰色:标记中

  白色:未标记

  并发漏标:解决办法增量更新法、原始快照法 

类加载

 类加载的三个阶段(类加载只会加载一次 )

  1.加载 

    类的字节码载入方法区,创建.class类到堆中

    如果此类的父类或者接口,没有加载,先要去加载父类、接口

    类的加载是懒加载(不用的时候是不加载的)

  2.链接

    验证类是否符合规范、安全检查

    为static 分配内存空间

    将常量池中的符号解析为直接引用(这是一个很慢的过程,不是一次性完成的)

  3.初始化:(懒惰)

  1. 静态属性:static 开头定义的属性
  2. 静态方法块: static {} 圈起来的方法块
  3. 普通属性: 未带static定义的属性
  4. 普通方法块: {} 圈起来的方法块
  5. 构造函数: 类名相同的方法
  6. 方法: 普通方法

调用final static修饰的基本变量,不会触发类的加载,调用final static修饰的引用变量,会触发类加载(非final静态属性,如果是final修饰的那么它在链接的第三步骤已经赋值了)

实例化:按照上面的顺序,但是不重新加载静态修饰的属性以及方法了,因为第一次初始化的时候,已经被加载过了,可以直接调用。直接运行2,3,4,5,6

 

 

 

普通类:
  • 静态变量
  • 静态代码块
  • 普通变量
  • 普通代码块
  • 构造函数
继承的子类:
  • 父类静态变量
  • 父类静态代码块
  • 子类静态变量
  • 子类静态代码块
  • 父类普通变量
  • 父类普通代码块
  • 父类构造函数
  • 子类普通变量
  • 子类普通代码块
  • 子类构造函数
抽象的实现子类: 接口 - 抽线类 - 实现类
  • 接口静态变量
  • 抽象类静态变量
  • 抽象类静态代码块
  • 实现类静态变量
  • 实习类静态代码块
  • 抽象类普通变量
  • 抽象类普通代码块
  • 抽象类构造函数
  • 实现类普通变量
  • 实现类普通代码块
  • 实现类构造函数
接口注意:
  • 声明的变量都是静态变量并且是final的,所以子类无法修改,并且是固定值不会因为实例而变化
  • 接口中能有静态方法,不能有普通方法,普通方法需要用defalut添加默认实现
  • 接口中的变量必须实例化
  • 接口中没有静态代码块、普通变量、普通代码块、构造函数
对象的引用类型
  强引用 A a=new A();
  软引用
  弱引用
  虚引用 
 
fianlize 关键字解释
  表层:Object的一个方法,子类可以重写,垃圾回收时可以调用,可以进行资源释放和清理。
     深层:将资源释放和清理放在finalize方法中非常不好,非常影响性能,严重甚至影响oom(内存溢出),从jdk9已经弃用
    1.fianlize方法调用不能保证执行顺序 。2.fianlize中的的代码不一定能够执行(finalize是守护线程,当主线程结束之后,守护线程代码不会执行)。3.fianlize代码中出现异常不会抛出(Fianlize对象中的try{}catch{}代码块没有做任何操作,直接吞掉了)。4.垃圾回收是不会立刻调用fianlize方法

 

 

Spring框架篇

  ApplicaltionContext----Refresh(共计12个方法,12 步骤)

  1.prepareRefresh

    创建和准备了Environment对象,Environment对象是用后续使用的提供一些键值对,1.系统环境变量中的键值对例如 JAVA_HOME ,2.java虚拟机提供的键值对,文件分隔符,默认编码

    3.自定义的键值对信息,例如 springboot中的applicaion.yml中的配置信息

  2.obtainFreshBeanFactory

    理解 :在代码关系上AppactionContext(子类)是继承于BeanFactory,但是实际应用的时候,很多AppactionContext的很多功能并没有自己实现(创建Bena、依赖初始化、依赖注入)还是通过成员

    变量BeanFactory来完成。在应用上,他们是组合关系,applicationcontext 在管理上借助了beanFactory的功能。

    作用:创建BeanFactory

    BeanFactory 在创建bean之前需要先知道bean的定义,这个定义是通过BeanDefinition类实现的,BeanDefinition定义Bean的单例,多例,依赖关系、初始化方式什么,那些属性需要依赖注入

    beanDefinitionMap方法存储所有的BeanDefinition。BeanDefinition可以从xml文件中获取bean、可以通过配置类获得(@Bean注解)、组件扫描获得(@Service)、也可以编程添加

 

 

 

 

 

 

 

    

 

posted @ 2022-04-12 13:40  幽灵中的野孩子  阅读(106)  评论(0编辑  收藏  举报