java杭州面试必问小结

alexander137 2017-10-11 11:42:38
1.垃圾回收之可达到性分析
即使在可达性分析中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历再次标记过程:
第一次标记(没有重写finalize,已经执行过finalize)
第二次标记(没有重写finalize,已经执行过finalize)
对象被回收
GC的回收策略
a.标记-清除算法
b.复制算法
c.标记整理算法(将存活的对象向左移动)
d.分代收集算法(新生代,年轻代,老年代,永久代)
“Mark-Sweep”算法分为“标记”和“清除”两个阶段:
标记出所有需要回收的对象
标记完成后统一回收所有被标记的对象
主要的不足之处:
内存碎片的问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续空间而不得不提前触发另一次垃圾收集动作。
“Copying”算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针按顺序分配内存即可,简单高效。
不足之处:
以空间换时间,将可用内存缩小为了原来的一半。
在对象存活率较高时就要进行较多的复制操作,需要额外的分配担保。


2.jvm运行过程
加载 将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口,这个过程需要类加载器参与。
链接 将java类的二进制代码合并到JVM的运行状态之中的过程
  验证:确保加载的类信息符合JVM规范,没有安全方面的问题
  准备:正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法去中进行分配
  解析:虚拟机常量池的符号引用替换为字节引用过程
初始化 初始化阶段是执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译器自动收藏类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生
当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化
虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步
当范围一个Java类的静态域时,只有真正声名这个域的类才会被初始化
使用
卸载

3.线程池
并发执行不一定快,因为有线程创建和调度的时间。
大于10ms的任务可以考虑并发执行。
慢的任务放在主线程里执行,快的任务放在子线程里执行。
可以考虑使用线程池,减少线程创建和上下文切换的消耗。



4.垃圾回收详解
什么是GC?
 既是一种内存管理机制,也是一种内存管理程序
 主要功能:内存自动分配和回收
 GC所关注的,就是Heap和Method Area,它主要工作在Heap上面
GC的主要职责?
 内存分配
 回收垃圾内存
 整理内存碎片

引用计数算法( Reference Counting ):
对象中添加一个引用计数器,每当有一个地方引用它时计数器值加1;当引用失效时计数器减1;任何时刻计数器都为0的对象就是不可能再被使用的。
问题:无法解决对象之间相互循环引用。

可达性分析算法(GC Roots Analysis):
通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径叫做引用链(Reference Chain)。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

5.生产者消费者模式
实际开发应用场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。
介绍:单单抽象出生产者和消费者,还够不上是生产者/消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。生产者把数据放入缓冲区,而消费者从缓冲区取出数据
功能:解耦,支持并发, 支持忙闲不均
对于并发问题: 生产者直接调用消费者的某个方法,还有另一个弊端。由于函数调用是同步的(或者叫阻塞的),在消费者的方法没有返回之前,生产者只好一直等在那边。万一消费者处理数据很慢,生产者就会白白糟蹋大好时光。使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体(常见并发类型有进程和线程两种,后面的帖子会讲两种并发类型下的应用)。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。其实当初这个模式,主要就是用来处理并发问题的。
当生产者生产的数据在缓冲区存满后,将信号量通知用户仓库已满,当消费者消费完仓库中的数据后,将会通知生产者生产数据.

6. HashMap和Hashtable的区别
HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。
HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。

7.TreeMap
基于红黑二叉树的NavigableMap的实现,线程非安全,不允许null,key不可以重复,value允许重复,存入TreeMap的元素应当实现Comparable接口或者实现Comparator接口,会按照排序后的顺序迭代元素,两个相比较的key不得抛出classCastException。主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出

8. LinkedHashMap:
是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。

9.hashset是通过hashmap实现的,treeset是通过treemap实现的

10. 互联网开发流程:
需求分析
=>系分设计(数据库,web请求,服务调用)详见< C:\Users\wb-zch276135\Desktop\开发\帮助中心需求1 >文件夹
=>开发时间确定,代码分支(acp地址)
=>开发机申请(访问ACP http://acp.mayibank.net/flow/devPattern/devObject/98716
=>线下环境
=>申请机器,选择ce的时候就是项目代码pom.xml里面的ce版本)
=>设置免密码登录
=>部署
=>建表(同样是在acp上建表)
=>生成dal层(set ANT_OPTS=-Xmx512m mvn antrun:run compile) 执行gen.bat
=>component组件开发
=>事件处理开发
=>管理器开发
=>控制层调试服务
=>接口调试(场景代码添加要到aone里面提需求)
=>与数据库对接工程fchelp服务maven发布(发布的时候fchelp工程下的facade下的pom.xml和全局pom的日期需求修改以及引用服务的fccsmng全局pom的配置日期修改)
=>两系统服务间调用调试(/home/admin/logs/tracelog外部系统调用本系统服务的日志)
=>前端开发
=>vm=>antd需要安装代理(有dev的和sit环境的,详见当前目录外部文档)
=>无线端开发(默认图片通过红蜻蜓系统进行上传而获得的图片url: https://rmsportal.alipay.com/)
=>分支合并
=>将fccsmng master代码更新到stable环境,切流操作
(http://gitlab.alipay-inc.com/mayibank_release/fccsmng/tree/master)
=>stable环境部署(admin/aqc_mayi)
=>数据库变更执行到sit环境
=>maven变更
=>sit环境前端部署(npm run deploy-sit 在本地运行的命令是npm run dev)
=>预发布环境antx配置变更
=>sit工程发布
=>acp中预发布申请
=>发布上线

11.数据存储中间介:Map/Reduce 和RDD

对于RDD:
• 它是不变的数据结构存储
• 它是支持跨集群的分布式数据结构
• 可以根据数据记录的key对结构进行分区
• 提供了粗粒度的操作,且这些操作都支持分区
• 它将数据存储在内存中,从而提供了低延迟性
5个特点
RDD是Spark提供的核心抽象,全称为Resillient Distributed Dataset,即弹性分布式数据集。
RDD在抽象上来说是一种元素集合,包含了数据。它是被分区的,分为多个分区,每个分区分布在集群中的不同节点上,从而让RDD中的数据可以被并行操作。(分布式数据集)
RDD通常通过Hadoop上的文件,即HDFS文件或者Hive表,来进行创建;有时也可以通过应用程序中的集合来创建。
RDD最重要的特性就是,提供了容错性,可以自动从节点失败中恢复过来。即如果某个节点上的RDD partition,因为节点故障,导致数据丢了,那么RDD会自动通过自己的数据来源重新计算该partition。这一切对使用者是透明的。
RDD的数据默认情况下存放在内存中的,但是在内存资源不足时,Spark会自动将RDD数据写入磁盘。(弹性)

12.spring aop理解
AOP核心概念
横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
连接点(joinpoint)--什么时候发生
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
切入点(pointcut)
对连接点进行拦截的定义
通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
目标对象
代理的目标对象
织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

织入方式有:运行时(jdk动态代理技术也是默认的),编译时(借用aspj技术进行切面编程=>编写类,定义切面,配置aop[配置的包括切点表达式,切面和通知]),类加载时

13.mvc


14.sofa mvc架构
关乎阿里架构,在此不说

15.sleep,wait,notify
sleep是Thread类的静态方法,谁调用谁去睡觉。sleep是占用cpu去睡觉,而wait是放弃cpu去睡觉, sleep没有释放锁,而wait释放了锁,sleep不会让出cpu资源,wait是进入线程池等待,一般wait是不会使用时间参数,他必须等待别人notify他才会进入就绪队中。而sleep只要时间到了,就会自动进入就绪队列。如果等不及了,只能通过interrupt来强项打断。
wait,notify以及notifyall只能在同步控制方法或者同步控制块中使用,而sleep可是在任何地方使用。
sleep必须捕获异常,而其他3个则不需要。
在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。

16. springmvc执行步骤DispatcherServlet在web.xml中的部署描述,从而拦截请求到Spring Web MVC
HandlerMapping的配置,从而将请求映射到处理器
HandlerAdapter的配置,从而支持多种类型的处理器
ViewResolver的配置,从而将逻辑视图名解析为具体视图技术
处理器(页面控制器)的配置,从而进行功能处理

17. 表分区有以下优点:
改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能。

缺点:
分区表相关:已经存在的表没有方法可以直接转化为分区表。不过 Oracle 提供了在线重定义表的功能。

18.git和svn的区别
Git是分布式的,SVN不是(自己写的代码放在自己电脑上,一段时间后再提交、合并,也可以不用联网在本地提交)
GIT把内容按元数据方式存储,而SVN是按文件
GIT没有一个全局的版本号,而SVN有
GIT的内容完整性要优于SVN(GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏)

19. 启动一个线程是用run()还是start()? 为什么?(一些初始化的操作)
启动线程肯定要用start()方法。当用start()开始一个线程后,线程就进入就绪状态,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。当cpu分配给它时间时,才开始执行run()方法(如果有的话)。start()是方法,它调用run()方法.而run()方法是你必须重写的. run()方法中包含的是线程的主体。如果简单的执行run方法 那就不是线程了

20.rebase和merge的区别
rebase也可以分支往主干,主干往分支,这只是方向的问题,真正的区别是历史版本的不一致,merge是产生一个新的节点,将两个分支的合并,rebase是丢弃分支的历史版本提交并临时保存为补丁然后依次提交到要合并到的分支,效果是不会有合并的痕迹
所以一般主干往分支合用rebase避免保留痕迹,这属于是默认行为了
分支往主干合是有人为干预,所以要用merge,要保留记录

21. 浅谈redis和memcached的区别
redis与 memcached相比,redis支持key-value数据类型,同事支持list、set、hash等数据结构的存储。
redis支持数据的备份,即master-slave模式的数据备份。
redis支持数据的持久化。
redis在很多方面支持数据库的特性,可以这样说他就是一个数据库系统,而memcached只是简单地K/V缓存。
它们在性能方面差别不是很大,读取方面尤其是针对批量读取性能方面memcached占据优势。当然redis也有他的优点,如持久性、支持更多的数据结构。
所以在选择方面如果有持久方面的需求或对数据类型和处理有要求的应该选择redis。
如果简单的key/value 存储应该选择memcached。

22. 对比MySQL,你究竟在什么时候更需要MongoDB
你期望一个更高的写负载
默认情况下,对比事务安全,MongoDB更关注高的插入速度。如果你需要加载大量低价值的业务数据,那么MongoDB将很适合你的用例。但是必须避免在要求高事务安全的情景下使用MongoDB,比如一个1000万美元的交易。
不可靠环境保证高可用性
设置副本集(主-从服务器设置)不仅方便而且很快,此外,使用MongoDB还可以快速、安全及自动化的实现节点(或数据中心)故障转移。
未来会有一个很大的规模
数据库扩展是非常有挑战性的,当单表格大小达到5-10GB时,MySQL表格性能会毫无疑问的降低。如果你需要分片并且分割你的数据库,MongoDB因为支持自动分片将很容易实现这一点。
使用基于位置的数据查询
MongoDB支持二维空间索引,因此可以快速及精确的从指定位置获取数据。
非结构化数据的爆发增长
给RDBMS增加列在有些情况下可能锁定整个数据库,或者增加负载从而导致性能下降,这个问题通常发生在表格大于1GB(更是下文提到BillRun系统中的痛点——单表格动辄几GB)的情况下。鉴于MongoDB的弱数据结构模式,添加1个新字段不会对旧表格有任何影响,整个过程会非常快速;因此,在应用程序发生改变时,你不需要专门的1个DBA去修改数据库模式。
缺少专业的数据库管理员
如果你没有专业的DBA,同时你也不需要结构化你的数据及做join查询,MongoDB将会是你的首选。MongoDB非常适合类的持久化,类可以被序列化成JSON并储存在MongoDB。需要注意的是,如果期望获得一个更大的规模,你必须要了解一些最佳实践来避免走入误区。

23.java继承的初始化顺序
 按定义时的顺序初始化基类的static成员
 按定义时的顺序初始化扩展类的static成员
(以上两条是对第一次定义扩展类对象时运行)
 按定义时顺序执行基类的指定初始化
 执行基类的构造函数
 按定义时的顺序执行扩展类的指定初始化
 行扩展类的构造函数

24. mysql为什么尽量不做连表查询:
1,mysql连表查询是比较慢的,相比先查出一个表的记录,然后再查另外一个表。
2,单表查询的数据方便做缓存。
3,连表查询是会锁多表,单表查询只锁单表。
4,如果以后需要分库分表,连表的sql语句就需要改了

25.spring 配置文件详解

26.springmvc对比struts2
struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入
struts2实际上是通过setter getter方法与request打交道的
struts2中,一个Action对象对应一个request上下文
spring3 mvc不同,spring3mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去
在spring3mvc中,一个方法对应一个request上下文
所以说从架构本身上 spring3 mvc就容易实现restful url
而struts2的架构实现起来要费劲
因为struts2 action的一个方法可以对应一个url
而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了

spring3mvc的方法之间基本上独立的,独享request response数据
请求数据通过参数获取,处理结果通过ModelMap交回给框架
方法之间不共享变量

而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的
这不会影响程序运行,却给我们编码 读程序时带来麻烦

spring3 mvc的验证也是一个亮点,支持JSR303
处理ajax的请求更是方便 只需一个注解@ResponseBody ,然后直接返回响应文本即可

注解和性能没有关系,Servlet的生命周期是这样的,在调用这个Servlet时候才创建这个Servlet的类并运行init()方法,然后另外有人运行这个Servlet的时候并没有重启创建Servlet和运行里边的init()方法,所以Servlet容器时单利的,spring就是Servlet的封装的框架,包括所有的依赖注入都是在tomcat启动的时候全部被初始化的,其他的注解也一样,也就是说注解也就是以前的xml的配置的替代,以前没个请求都要运行一次xml吗?并不是的,xml是在tomcat启动时就读一次而已并利用里边的配置初始化很多的东西,然后就不在使用了,因为都成了单例的,这样就保证了效率,不是每次都把我们要注入的全部new一次,而是tomcat启动的时候全部new一次以后就不new了,保证了效率问题。

所以我不明白那个 光看注解就知道性能不好?
注解就是替代了xml配置而已,而且也是初始化一次,也就是说和编写Servlet一样的在init()中做了很多的事而已,并且以后不会在运行init()了,除非你重启tomcat。

struts1也一样,运行一个action的方法的时候创建一个action类,以后再运行就不会创建了,其实也是Servlet的封装的框架。
struts2特殊一些,没个请求要new一个action来保证线程安全。所以效率会低一些,但是不会低的特别离谱。




...全文
289 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
alexander137 2017-10-11
  • 打赏
  • 举报
回复
接下来有时间还会总结的

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧