Skip to content

Latest commit

 

History

History
83 lines (66 loc) · 7.14 KB

Java语言基础面试八股题整理03.org

File metadata and controls

83 lines (66 loc) · 7.14 KB

Java语言基础面试八股题整理03

Java系列小问题

  1. 字符串是匿名对象,例如“hello”.toString()。但如果已经实例化后,堆内存的地址已经有了明确的栈内存指向就不是匿名对象了,例如:String str = “hello”。
  2. 只要是引用对象就保存在堆内存里面,而我们所能进行的内存控制,也只有堆内存。
  3. 不管是对象池还是常量池都保存在堆内存中
  4. 对于JVM有三种实现标准,我们使用的是HotSpot虚拟机标准,这个标准的实现不是简单调用了底层的函数。它里面需要与一些底层设备交互,而整个系统设计之中,为了可以让java调用本地的函数功能,专门提供有一个native交由JVM负责实现一些具体功能。

JVM核心优化策略

  1. 取消掉伸缩区,total=max;
    • CMS(Concurrent Mark Sweep)问题,频繁的CMS会导致性能下降;
    • 伊甸园区、存活区、老年代的关系要说明白,JDK1.8之后取消了永久代,而使用元空间代替;
  2. 如果内存使用过大要使用G1收集器来进行收集;
  3. 在Tomcat里面由于其使用基于JVM,所以需要设置一个“JAVA_OPTS”,可以将全部的内存供Tomcat使用(默认的最大可用内存为全部的四分之一,默认的total内存为全部内存的64分之1)。

JVM内存组成

JVM内存组成里面最为关键的几个内存:

  • 栈内存:只是保存有堆内存的引用地址,而且从一个简单的角度来讲,栈内存可以保存基本类型(int、double等)
  • 堆内存:java没有采用句柄的模式进行引用,所以它的引用性能是最高的,但是从另一个角度来讲,堆内存里面实际上又分为了若干个子内存空间:伊甸园区(MinorGC)、存活区、老年代(FullGC、MajorGC)。
    • 原则:少产生无用的大量内存空间,因为会引发频繁的GC,而频繁的GC会带来CMS问题,那么会导致程序中断执行。
    • 原则:让你初始化的空间等于整个堆内存的分配大小,避免伸缩区,这样可以进行性能的提升。
  • 方法区:(JDK1.8以前可以称为永久代,在1.8之后称为元空间)

全局数据区也可以认为其规划在堆内存里面,因为可能是对象,可能是基本类型,只不过是采用了一种特殊的处理形式而已。

常见问题:JVM的堆内存组成?GC的处理流程?

Map-Resize

如果大于最大,将其设置整型最大值。

它的容量扩充指的是一开始放30个,如果发现不够,则进行移位处理,相当于扩大一倍(30*2),再不够,再移位一次,扩容相当于倍数处理。

Runtime相关说明

java.lang.Runtime类是一个系统提供的单例开发类,一个JVM中只存在一个Runtime实例。

  • 可以获取系统信息
  • 可以进行GC处理(对于整个的JVM内存划分是存在伸缩区,所以面对这样的问题,为了可以提升性能,将初始化内存和最大内存设为相同,如果不相同,就会一直进行空间的判断,而后不断进行空间分配。(-Xmx1g -Xmn1g))。

RuntimeException的异常子类不需要强制性处理,可以选择性处理。Exception的其它子类必须进行处理。RuntimeException是Exception的子类。

String转换

Object类之中提供有一个toString()方法,意味着所有的类都具有此方法,此方法的作用就是将对象的内容转化为字符串。

// object默认返回的值
getClass().getName() + '@' + Integer.toHexString(hashCode())

考虑ClassLoader的机制,强转以及子类复写的情况。

如果使用的是String,那么在不为null的情况下,使用强制转型和toString()方法效果一样,但是如果为null,则就会出现NullPointerException。保险的做法是:使用强制转型,但是如果在确定不为空的情况下,则两种方式对String操作的效果是一样的(只有String是,其它的都没有,其它的类如果要变为指定类型只能使用强制向下转型)。

ThreadLocal

java是多线程的,static保存的是全局数据区,属于公共的数据处理。在多线程处理中就会出现数据不同步的问题。

那么最好的做法是在可以保存数据的基础上在再多保存一个当前线程对象。而这种操作就属于ThreadLocal类的作用,也就是说ThreadLocal在每一次设置内存的时候都会保存一个当前线程对象。

在ThreadLocal开发中往往保存的最多的是数据库的连接对象。这种场景也特别适合ThreadLocal。

ThreadLocal和Threadpool

这两个是没有关系的。

  • ThreadLocal类是可以保存一个引用数据类型,并且这个引用数据类型保存的时候会自动保存有一个currentThread对象,这样的好处就是可以避免引用传递的问题。
  • ThreadPool指的是线程池,也就是说提供有一个对象池,这个对象池里有若干个线程对象,帮助我们进行可重复使用的对象的生成。线程池种类:无限制增长、定长执行、定时操作、单线程池。

ThreadLocal很少出现在程序的开发之中,主要在数据管理中。ThreadPool就是给线程重用的操作。

ThreadLocal引用传递

TheadLocal的本身作用就是进行操作对象信息保存,但它与传统的信息保存不同,它不仅仅保存的是一个引用对象,而且还保存有一个当前对象。也就是说进行数据保存的时候ThreaLocal更像Map集合。

在进行数据保存的引用传递的时候不再只是一个引用类型,而是包含有一个currentThread对象信息保存。这样就可以明确的知道当前操作的对象是什么,并且不会与其它线程进行混淆。

YML格式

yml格式是与properties对应的一种格式,基本上可以方便的描述资源配置。

抽象类

抽象类只是比一个普通类多了抽象方法的类而已,其它的结构和普通类是差不多。还有一个使用上的区别就是抽象类无法直接使用关键字new进行实例化控制。

普通类的最大的特征在于其定义了类的结构之后可以直接使用关键字new进行对象实例化,但是从继承的角度来看,普通类的继承里面对于子类没有强制性约束。

如果现在某些方法的必须要求子类来实现,那么就可以使用抽象类。

所有的关键字new调用构造方法实例化对象的部分可以将其理解为“匿名对象”的语法。

抽象类基础

理论上是抽象类的方法必须覆写,但是为什么HttpServlet的子类中覆写或者不覆写都不会报错?

关键的问题在于HttpServlet抽象类中的所有方法并不完全都是抽象方法,对于抽象类的子类需要覆写的只是抽象方法,对于非抽象方法是不需要强制覆写的。

例子:模版设计模式。