您的位置 首页 java

(答案三) 高级Java面试试题

开源框架知识

1、简单讲讲 Tomcat 结构,以及其类加载器流程, 线程 模型等。

模块组成结构:

Tomcat 的核心组件就 Connector 和 Container,一个Connector+一个Container(Engine)构成一个Service,Service就是对外提供服务的组件,有了Service组件Tomcat就能对外提供服务了,但是光有服务还不行,还需要有环境让你提供服务才行,所以最外层的 Server 就是为Service提供了生存的土壤。

(答案三) 高级Java面试试题

Connector是一个连接器,主要负责接受请求并把请求交给Container,Container就是一个容器,主要装的是具有处理请求的组件。Service主要是为了关联 Container与 Connect,只有两个结合起来才能够处理一个请求。Server负责管理 Service集合,从图中我们可以看到Tomcat可以提供多种服务,那么这些Service就是由Server来管理的。具体工作包括:对外提供一个接口访问Service,对内维护 Service集合,维护 Service集合包括管理 Service声明周期等等。

类加载器流程

(答案三) 高级Java面试试题

当tomcat启动时,会创建几种类加载器:

1 bootstrap 引导类加载器

加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下)

2 System 系统类加载器

加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下

3 Common 通用类加载器

加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar

4 webapp 应用类加载器

每个应用在部署后,都会创建一个唯一的类加载器。该类加载器会加载位于 WEB-INF/lib下的jar文件中的class 和 WEB-INF/classes下的class文件。

当应用需要到某个类时,则会按照下面的顺序进行类加载:

1 使用bootstrap引导类加载器加载

2 使用system系统类加载器加载

3 使用应用类加载器在WEB-INF/classes中加载

4 使用应用类加载器在WEB-INF/lib中加载

5 使用common类加载器在CATALINA_HOME/lib中加载

线程模型

(答案三) 高级Java面试试题

2、tomcat如何调优,涉及哪些参数 。

Tomcat 的缺省配置是不能稳定长期运行的,也就是不适合生产环境,它会死机,让你不断重新启动,甚至在午夜时分唤醒你。对于操作系统优化来说,是尽可能地增大可使用的内存容量、提高CPU 的频率,保证文件系统的读写速率等。经过压力测试验证,在并发连接很多的情况下,CPU 的处理能力越强,系统运行速度越快。

硬件上选择,操作系统选择,版本选择,jdk选择,配置jvm参数,配置connector的线程数量,开启gzip压缩,trimSpaces,集群等
a) 内存优化:主要是对Tomcat启动参数进行优化,我们可以在Tomcat启动脚本中修改它的最大内存数等等。

b) 线程数优化:Tomcat的并发连接参数,主要在Tomcat配置文件中server.xml中配置,比如修改最小空闲连接线程数,用于提高系统处理性能等等。

c) 优化缓存:打开压缩功能,修改参数,比如压缩的输出内容大小默认为2KB,可以适当地修改。

3、讲讲Spring加载流程。

3.1. 转化 bean Name
3.2. 合并 RootBeanDefinition
3.3. 处理循环依赖
3.4. 创建实例
3.5. 注入属性
3.6. 初始化
3.7. 类型转换

(答案三) 高级Java面试试题

4、Spring AOP 的实现原理。

实现AOP的主要设计模式就是动态代理。
Spring的动态代理有两种:一是JDK的动态代理;另一个是cglib动态代理。

5、讲讲Spring事务的传播属性。

所谓spring事务的传播属性,就是定义在存在多个事务同时存在的时候,spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义,具体常量的解释见下表:

6、Spring如何管理事务的。

1、就是@Transactional注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。

2、方法必须是public修饰符。否则注解不会生效,但是加了注解也没啥毛病,不会报错,只是没卵用而已。

3、this.本方法的调用,被调用方法上注解是不生效的,因为无法再次进行切面增强。

7、Spring怎么配置事务(具体说出一些关键的xml 元素)。

一般都是 @Transactional 注解完事儿,里面有一些属性字段,看自己需求配置即可

8、说说你对Spring的理解,非单例注入的原理?它的生命周期?循环注入的原理,aop的实现原理,说说aop中的几个术语,它们是怎么相互工作的。

Spring的理解:1)、Spring是一个开源框架,主要是为简化企业级应用开发而生。可以实现EJB可以实现的功能,Spring是一个IOC和AOP容器框架。

♧ 控制反转(IOC):Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。

♧ 依赖注入(DI):Spring使用Java Bean对象的Set方法或者带参数的构造方法为我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本思想。

♧ 面向切面编程(AOP):在面向对象编程(OOP)思想中,我们将事物纵向抽象成一个个的对象。而在面向切面编程中,我们将一个个对象某些类似的方面横向抽象成一个切面,对这个切面进行一些如权限验证,事物管理,记录日志等公用操作处理的过程就是面向切面编程的思想。

2)、在Spring中,所有管理的都是 JavaBean 对象,而BeanFactory和ApplicationContext就是Spring框架的那个IOC容器,现在一般使用ApplicationContext,其不但包括了BeanFactory的作用,同时还进行了更多的扩展。

✔ 非单例注入原理:在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean或者一个非singleton bean要引用另外一个非singleton,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例。

9、Springmvc 中DispatcherServlet初始化过程。

 DispatcherServlet extends FrameworkServlet extends HttpServletBean extends HttpServlet

初始化:HttpServletBean.init() -> FrameworkServlet.initServletBean -> FrameworkServlet.initWebApplicationContext()

initWebApplicationContext: 

1. 调用WebApplicationContextUtils.getWebApplicationContext( ServletContext )获取当前 web容器 中的根WebApplicationContext rootContext,该rootContext通常由ContextLoaderListener生成(因为该方法实际是获取web容器中attrName为 org .springframework.web.context.WebApplicationContext.ROOT的WebApplicationContext,而该attrName由ContextLoaderListener设置到web容器中)

2. 判断本Servlet所属的WebApplicationContext wac是否在init之前就由别的步骤注入了?即判断wac是否为null

2.1. 若非空(wac已存在),则将rootContext设为wac的parent,再调用configureAndRefreshWebApplicationContext(wac)

2.2. 若为空(wac不存在),则先调用findWebApplicationContext寻找web容器中是否已经存在同名(attrName,定义见5)的WebApplicationContext(首次启动web容器时通常不存在;当servlet初始化失败,web容器自动重启时可能存在),若还是不存在则调用createWebApplicationContext生成一个新的WebApplicationContext

2.2.1. createWebApplicationContext(rootContext): 首先创建一个全新的WebApplicationContext wac,再将rootContext设为wac的parent,再调用configureAndRefreshWebApplicationContext(wac)

3. configureAndRefreshWebApplicationContext(wac): 先设置wac的各项配置和环境参数,后调用wac.refresh()

4. DispatcherServlet.onRefresh(wac): 初始化与web mvc相关的spring组件

5. 调用ServletContext.setAttribute将wac注册到web容器中,attrName为org.springframework.web.servlet.FrameworkServlet.CONTEXT.${servlet-name  

10、 netty 的线程模型,netty如何基于reactor模型上实现的。

(1)Reactor单线程模型

(2)Reactor 多线程 模型

(3)主从Reactor多线程模型

(4)netty的多线程模型

Netty整体架构是Reactor模型,采用epoll机制,所以往深地说还是IO多路复用模式,所以可以说Netty是同步非阻塞模型。但是很多人说这是netty基于 Java NIO类库实现的异步通信框架。

Netty特点是:异步非阻塞,基于事件驱动,性能高,高可靠性,高可定制性。

11、为什么选择netty。

开发出高质量的NIO 程序并不是一件简单的事情,除去NIO 固有的复杂性和Bug不谈,作为一个NIO 服务端,需要能够处理网络的闪断、客户端的重复接入、客户端的安全认证、消息的编解码、半包读写等情况, 如果你没有足够的NIO 编程经验积累, 一个NIO 框架的稳定往往需要半年甚至更长的时间。更为糟糕的是, 一旦在生产环境中发生问题, 往往会导致跨节点的服务调用中断, 严重的可能

会导致整个集群环境都不可用, 需要重启服务器,这种非正常停机会带来巨大的损失。

从可维护性角度看,由于NIO 采用了异步非阻塞编程模型,而且是一个I/O 线程处理多条链路,它的调试和跟踪非常麻烦, 特别是生产环境中的问题,我们无法进行有效的调试和跟踪, 往往只能靠一些日志来帮助分析,定位难度很大。

对于java原生的IO我们之所以不选择使用是因为:

NIO的类库和API繁杂使用麻烦,你需要熟练掌握Selectol,ServerSocketChannel,

SocketChannel,ByteBuffer 等。

需要具备其他的额外技能做制垫,例如熟悉Java 多线程编程。这是因为NIO编程涉及到Reactor 模式,你必须对多线程和网络编程非常熟悉,才能编写出高质量的NIO程序。

可靠性能力补齐, 工作量和难度都非常大。例如客户端面临断连重连、网络间断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题, NI0 编程的特点是功能开发相对容易,但是可靠性能力补齐的工作量和难度都非常大。

JDK NIO的BUG,比如epoll bug,这个BUG会在linux上导致cpu 100%,使得nio server/client不可用,这个BUG直到jdk 6u4才解决,但是直到JDK1.7中仍然有这个问题,该问题并未被完全解决,只是发生的频率降低了而已。

基于上述原因大多数场景下都不建议直接使原生NIO,除非你精通NIO编程或者是有特殊的需要,否则作为服务器编程的NIO可能会带来巨大的生产隐患。

12、netty的心跳处理在弱网下怎么办。

  1. 使用 Netty 实现心跳机制的关键就是利用 IdleStateHandler 来产生对应的 idle 事件.
  2. 一般是客户端负责发送心跳的 PING 消息, 因此客户端注意关注 ALL_IDLE 事件, 在这个事件触发后, 客户端需要向服务器发送 PING 消息, 告诉服务器”我还存活着”.
  3. 服务器是接收客户端的 PING 消息的, 因此服务器关注的是 READER_IDLE 事件, 并且服务器的 READER_IDLE 间隔需要比客户端的 ALL_IDLE 事件间隔大(例如客户端ALL_IDLE 是5s 没有读写时触发, 因此服务器的 READER_IDLE 可以设置为10s)
  4. 当服务器收到客户端的 PING 消息是, 会发送一个 PONG 消息作为回复. 一个 PING-PONG 消息对就是一个心跳交互.
  5. 断线重连的关键一点是检测连接是否已经断开. 因此我们改写了 ClientHandler, 重写了 channelInactive 方法. 当 TCP 连接断开时, 会回调 channelInactive 方法, 因此我们在这个方法中调用 client.doConnect() 来进行重连.

13、netty的通讯协议是什么样的。

二种实现方式:

  • 第一种方式利用了自定义协议,传递消息的时候,对消息的前几位(比如2位)进行自定义的位置(比如AB)解码器解析的时候前二位为AB表示一种协议类型,CD一种协议类型。这种方式没有利用protobuf,而是直接使用Netty自定义协议来解决的方案。
  • 第二种方式使用protobuf来实现,实际上是对消息的定义方式进行规定,因为netty本身,客户端和服务器端建立的是一条TCP连接,一方必须要判断对方发送过来的对象是什么类型。

14、springmvc用到的注解,作用是什么,原理。

复制代码

@Controller 声明Action组件

@Service 声明Service组件 @Service(“myMovieLister”)

@Repository 声明Dao组件

@Component 泛指组件, 当不好归类时.

@RequestMapping(“/menu”) 请求映射

@Resource 用于注入,( j2ee提供的 ) 默认按名称装配, @Resource(name=”beanName”)

@Autowired 用于注入,(srping提供的) 默认按类型装配

@Transactional( rollbackFor={Exception.class}) 事务管理

@ResponseBody

@Scope(“prototype”) 设定bean的作用域

原理的话,自己根据自己需要感兴趣的注解,去转向了解一下吧,太多了,,写不完。。

15、springboot启动机制。

我们可以将自动配置的关键几步以及相应的注解总结如下:

@Configuration&与@Bean——>>>基于java代码的bean配置

@Conditional——–>>>>>>设置自动配置条件依赖

@EnableConfigurationProperties与@ConfigurationProperties->读取配置文件转换为bean。

@EnableAutoConfiguration、@AutoConfigurationPackage 与@Import->实现bean发现与加载。

文章来源:智云一二三科技

文章标题:(答案三) 高级Java面试试题

文章地址:https://www.zhihuclub.com/182336.shtml

关于作者: 智云科技

热门文章

网站地图