java进阶面试题

JVM相关:

jvm中一次完整的GC流程(从ygc到fgc)是怎样的,重点讲讲对象如何晋升到老年代,几种主要的jvm参数等

新生代GC ygc(Minor GC):指发生新生代的的垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。
老年代GC fgc(Major GC/Full GC):指发生在老年代的GC,出现了Major GC经常会伴随至少一次的Minor GC(并非绝对),Major GC的速度一般会比Minor GC的慢10倍以上
大对象直接进入老年代
大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。
为了避免为大对象分配内存时由于分配担保机制带来的复制而降低效率。
既然虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别那些对象应放在新生代,那些对象应放在老年代中。为了做到这一点,
虚拟机给每个对象一个对象年龄(Age)计数器。
如果对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为1.
对象在 Survivor 中每熬过一次 MinorGC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,
可以通过参数 -XX:MaxTenuringThreshold 来设置。

比较重要的jvm参数

 -Xss:每个线程的栈大小
  -Xms:初始堆大小,默认物理内存的1/64
  -Xmx:最大堆大小,默认物理内存的1/4
  -Xmn:新生代大小
  -XX:NewSize:设置新生代初始大小
  -XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3。
  -XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。
 -XX:MetaspaceSize:设置元空间大小
  -XX:MaxMetaspaceSize:设置元空间最大允许大小,默认不受限制,JVM Metaspace会进行动态扩展。
垃圾回收统计信息
  -XX:+PrintGC
  -XX:+PrintGCDetails
  -XX:+PrintGCTimeStamps 
  -Xloggc:filename
收集器设置
  -XX:+UseSerialGC:设置串行收集器
  -XX:+UseParallelGC:设置并行收集器
  -XX:+UseParallelOldGC:老年代使用并行回收收集器
  -XX:+UseParNewGC:在新生代使用并行收集器
  -XX:+UseParalledlOldGC:设置并行老年代收集器
  -XX:+UseConcMarkSweepGC:设置CMS并发收集器
  -XX:+UseG1GC:设置G1收集器
  -XX:ParallelGCThreads:设置用于垃圾回收的线程数
并行收集器设置
  -XX:ParallelGCThreads:设置并行收集器收集时使用的CPU数。并行收集线程数。
  -XX:MaxGCPauseMillis:设置并行收集最大暂停时间
  -XX:GCTimeRatio:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
CMS收集器设置
  -XX:+UseConcMarkSweepGC:设置CMS并发收集器
  -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
  -XX:ParallelGCThreads:设置并发收集器新生代收集方式为并行收集时,使用的CPU数。并行收集线程数。
  -XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩
  -XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收
  -XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收
  -XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况
  -XX:ParallelCMSThreads:设定CMS的线程数量
  -XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发
  -XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理	
G1收集器设置 
  -XX:+UseG1GC:使用G1收集器
  -XX:ParallelGCThreads:指定GC工作的线程数量
  -XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区
  -XX:GCTimeRatio:吞吐量大小,0-100的整数(默认9),值为n则系统将花费不超过1/(1+n)的时间用于垃圾收集
  -XX:MaxGCPauseMillis:目标暂停时间(默认200ms)
  -XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%)
  -XX:G1MaxNewSizePercent:新生代内存最大空间
  -XX:TargetSurvivorRatio:Survivor填充容量(默认50%)
  -XX:MaxTenuringThreshold:最大任期阈值(默认15)
  -XX:InitiatingHeapOccupancyPercen:老年代占用空间超过整堆比IHOP阈值(默认45%),超过则执行混合收集
  -XX:G1HeapWastePercent:堆废物百分比(默认5%)
  -XX:G1MixedGCCountTarget:参数混合周期的最大总次数(默认8)
  • 你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms
1.Serial(串行)收集器收集器
Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 “单线程” 的意义不仅仅意味着它只会使用一条
垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束
新生代采用复制算法,老年代采用标记-整理算法。

2.ParNew收集器
ParNew收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和Serial收集器完全一样。
新生代采用复制算法,老年代采用标记-整理算法。

3.Parallel Scavenge收集器
Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户
代码的时间与CPU总消耗时间的比值。 Parallel Scavenge收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解的话,
可以选择把内存管理优化交给虚拟机去完成也是一个不错的选择。
新生代采用复制算法,老年代采用标记-整理算法。
4.CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它而非常符合在注重用户体验的应用上使用,
它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
初始标记: 暂停所有的其他线程(STW),并记录下直接与root相连的对象,速度很快 ;
并发标记: 同时开启GC和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象
。因为用户线程可能会不断的更新引用域,所以GC线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。
重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,
这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短
并发清除: 开启用户线程,同时GC线程开始对未标记的区域做清扫。
从它的名字就可以看出它是一款优秀的垃圾收集器,主要优点:并发收集、低停顿。但是它有下面三个明显的缺点:
对CPU资源敏感(会和服务抢资源);
无法处理浮动垃圾(在java业务程序线程与垃圾收集线程并发执行过程中又产生的垃圾,这种浮动垃圾只能等到下一次gc再清理了);
它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。

5.G1收集器
G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征.
G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的Region(这也就是它的名字Garbage-First的由来)。
这种使用Region划分内存空间以及有优先级的区域回收方式,保证了GF收集器在有限时间内可以尽可能高的收集效率。

Serial(串行)收集器收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y7oxgsRE-1596716243928)(7E107621F4D64DA683991F7A2F361164)]

ParNew收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OM4wUXG6-1596716243929)(9B2FF104DDF342909C5AC20ABAA18F6A)]

Parallel Scavenge收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TENaY4aO-1596716243930)(CF8215C1AB444B75A5C94631377F7F35)]

CMS收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2qWKfe0O-1596716243931)(FD85460B1D644F43953A6C37506DD4A7)]

G1收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RWBaA4tJ-1596716243932)(844683718D624C78A90FDF3D65C19A33)]

  • 当出现了内存溢出,你怎么排错
jmap -dump:format=b,file=eureka.hprof 13988
也可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导不出来)
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./   (路径)
用jstack查找死锁,见如下示例,也可以用jvisualvm查看死锁
jstack找出占用cpu最高的堆栈信息
1,使用命令top -p <pid> ,显示你的java进程的内存情况,pid是你的java进程号,比如4977
2,按H,获取每个线程的内存情况 
3,找到内存和cpu占用最高的线程tid,比如4977 
4,转为十六进制得到 0x1371 ,此为线程id的十六进制表示
5,执行 jstack 4977|grep -A 10 1371,得到线程堆栈信息中1371这个线程所在行的后面10行 
6,查看对应的堆栈信息找出可能存在问题的代码
  • JVM内存模型的相关知识了解多少
本地方法栈(线程私有): 
登记native方法,在Execution Engine执行时加载本地方法库
程序计数器(线程私有): 
就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,也即将要执行的指令代码)
,由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。
方法区(线程共享):
类的所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。简单说,
所有定义的方法的信息都保存在该区域,静态变量+常量+类信息(构造方法/接口定义)+运行时常量池都存在方法区中,
虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做 Non-Heap(非堆),目的应该是与 Java 堆区分开来。
Java栈(线程私有):
Java线程执行方法的内存模型,一个线程对应一个栈,每个方法在执行的同时都会创建一个栈帧(用于存储局部变量表,操作数栈,动态链接,方法出口等信息)
不存在垃圾回收问题,只要线程一结束该栈就释放,生命周期和线程一致
堆(线程共享):
虚拟机启动时创建,用于存放对象实例,几乎所有的对象(包含常量池)都在堆上分配内存,当对象无法再该空间申请到内存时将抛出OutOfMemoryError异常。
同时也是垃圾收集器管理的主要区域。可通过 -Xmx –Xms 参数来分别指定最大堆和最小堆

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r68QCkuP-1596716243933)(650F4E1F0AB84820A0850468993577C8)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c9s0i9XG-1596716243934)(6C1C513C96FF47C0A360B1D055C846CE)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUKARr4p-1596716243934)(309406ACC0E149B7BF890C573A079A48)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eBbCXxtr-1596716243934)(02A21FCC13194D9C827386567A40C960)]

  • 简单说说你了解的类加载器
启动类加载器:负责加载JRE的核心类库,如jre目标下的rt.jar,charsets.jar等
扩展类加载器:负责加载JRE扩展目录ext中JAR类包
系统类加载器:负责加载ClassPath路径下的类包
用户自定义加载器:负责加载用户自定义路径下的类包
全盘负责委托机制:当一个ClassLoader加载一个类时,除非显示的使用另一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入
双亲委派机制:指先委托父类加载器寻找目标类,在找不到的情况下在自己的路径中查找并载入目标类
双亲委派模式优势
沙箱安全机制:自己写的String.class类不会被加载,这样便可以防止核心API库被随意篡改
避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再   加载一次

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-86RlLf03-1596716243935)(A97D1F3D6C804FC8A62A31F683752EFC)]

  • JAVA的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,
都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
java通常是先有类再有对象,有对象我就可以调用方法或者属性。反射其实是通过Class对象来调用类里面的方法。通过反射可以调用私有方法和私有属性。

网络:

http1.0和http1.1有什么区别


1、HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理

HTTP 1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪每个客户也不记录过去的请求。

HTTP 1.1则支持持久连接Persistent Connection, 并且默认使用persistent connection. 在同一个tcp的连接中可以传送多个HTTP请求和响应. 多个请求和响应可以重叠,多个请求和响应可以同时进行. 更加多的请求头和响应头(比如HTTP1.0没有host的字段).

在1.0时的会话方式:

  1. 建立连接
  2. 发出请求信息
  3. 回送响应信息
  4. 关掉连接

HTTP 1.1的持续连接,也需要增加新的请求头来帮助实现,例如,Connection请求头的值为Keep-Alive时,客户端通知服务器返回本次请求结果后保持连接;Connection请求头的值为close时,客户端通知服务器返回本次请求结果后关闭连接。HTTP 1.1还提供了与身份认证、状态管理和Cache缓存等机制相关的请求头和响应头。

请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。例如:一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。 HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容。

2.HTTP 1.1增加host字段

在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。

HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。此外,服务器应该接受以绝对路径标记的资源请求。

3、100(Continue) Status(节约带宽)

HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。100 (Continue) 状态代码的使用,允许客户端在发request消息body之前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。

4、HTTP/1.1中引入了Chunked transfer-coding来解决上面这个问题,发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。

5、HTTP/1.1在1.0的基础上加入了一些cache的新特性,当缓存对象的Age超过Expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新激活(revalidation)。


TCP三次握手和四次挥手的流程,为什么断开连接要4次,如果握手只有两次,会出现什么

TCP连接建立过程:
1、客户端向服务器发送SYN(同步序列编号 Synchronize Sequence Numbers),其中seq=x(seq 序号 ack 确认号)。
2、服务器收到SYN报文段后,发送SYN+ACK,其中seq=y,确认号=x+1。
3、客户端收到SYN+ACK报文段后,发送ACK,确认号=y+1。服务器收到ACK报文段后,连接建立。
TCP连接断开过程:
1、客户端TCP模块在收到应用程序的通知后,发送FIN,seq=x。
2、服务器收到FIN报文段,发送ACK,确认号=x&
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

happyProgrammerWANG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值