PHP果然是最好的语言
maven
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.
Lifecycle
- validate: 用于验证项目的有效性和其项目所需要的内容是否具备
- initialize:初始化操作,比如创建一些构建所需要的目录等。
- generate-sources:用于生成一些源代码,这些源代码在compile phase中需要使用到
- process-sources:对源代码进行一些操作,例如过滤一些源代码
- generate-resources:生成资源文件(这些文件将被包含在最后的输入文件中)
- process-resources:对资源文件进行处理
- compile:对源代码进行编译
- process-classes:对编译生成的文件进行处理
- generate-test-sources:生成测试用的源代码
- process-test-sources:对生成的测试源代码进行处理
- generate-test-resources:生成测试用的资源文件
- process-test-resources:对测试用的资源文件进行处理
- test-compile:对测试用的源代码进行编译
- process-test-classes:对测试源代码编译后的文件进行处理
- test:进行单元测试
- prepare-package:打包前置操作
- package:打包
- pre-integration-test:集成测试前置操作
- integration-test:集成测试
- post-integration-test:集成测试后置操作
- install:将打包产物安装到本地maven仓库
- deploy:将打包产物安装到远程仓库
在maven中,你执行任何一个phase时,maven会将其之前的phase都执行。例如 mvn install,那么maven会将deploy之外的所有phase按照他们出现的顺序一次执行。
打包发布
jar包发布
- JavaTM Archive (JAR) file 即java存档文件
- 开发时要引用通用类,打成包便于存放管理
- 安全,快速下载,压缩,猎取包,版本化包,可携
- JAR文件的格式是ZIP格式的, 因此它可以用各种能够处理ZIP文件的工具来进行操作
war包发布
- 做好一个web应用后,通常是网站,打成包部署到容器中
- 在tomcat中我们就不能再用jar这种格式,而改war格式,它是专门用于web应用的
装箱和拆箱
自动装箱就是将原始类型自动的转换为对应的对象,而拆箱就是将对象类型转换为基本类型
垃圾回收机制
在Java中,不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。 垃圾回收算法
- 引用计数算法
- 标记-清扫算法
- 复制算法
- 标记-整理算法
- 分代收集算法
什么样的对象会被回收
- 不被任何线程或者静态变量引用的对象将被回收,主要分为以下四种情况:
- 对象被明确设置成null;
- 对象在区域内创建,并且工作线程已经离开这个区域;
- 对象的容器对象被设置成null,比如objectRoot引用了一堆object,那么当objectRoot被设置为null的时候,所有被它引用的对象也将被回收;
- 只被weakhashmap应用的对象;
Young GC
新对象创建好了之后,就会被分配在新生代中。一般等到Eden区满了之后会触发YGC。YGC做了以下的事情
- 将Eden区的需要回收的对象回收了;
- 将Eden区内的没有被回收的对象移动到空的Survivor中;
- 将有数据的Survivor区中的对象回收了;
- 将有数据的Survivor区中的复合条件的对象移动到空的Survivor中;
- 将有数据的Survivor区中的复合条件的对象移动到老年代中。
Full GC
一般是老年区满了才会触发FullGC,使用的是Mark-Sweep-Compact的算法:
- Mark:对有用的引用进行标记;
- Sweep:对垃圾进行清理;
- Compact:对活着的对象进行迁移,挪到一块来,解决内存碎片问题。
HashMap原理
HashMap内部是通过一个数组实现的,只是这个数组比较特殊,数组里存储的元素是一个Entry实体(jdk 8为Node),这个Entry实体主要包含key、value以及一个指向自身的next指针。HashMap是基于hashing实现的,当我们进行put操作时,根据传递的key值得到它的hashcode,然后再用这个hashcode与数组的长度进行模运算,得到一个int值,就是Entry要存储在数组的位置(下标);当通过get方法获取指定key的值时,会根据这个key算出它的hash值(数组下标),根据这个hash值获取数组下标对应的Entry,然后判断Entry里的key,hash值或者通过equals()比较是 否与要查找的相同,如果相同,返回value,否则的话,遍历该链表(有可能就只有一个Entry,此时直接返回null),直到找到为止,否则返回null。 HashMap之所以在每个数组元素存储的是一个链表,是为了解决hash冲突问题,当两个对象的hash值相等时,那么一个位置肯定是放不下两个值的,于是hashmap采用链表来解决这种冲突,hash值相等的两个元素会形成一个链表。
日志级别
- TRACE – The TRACE Level designates finer-grained informational events than the DEBUG
- DEBUG – The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
- INFO – The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
- WARN – The WARN level designates potentially harmful situations.
- ERROR – The ERROR level designates error events that might still allow the application to continue running.
- FATAL – The FATAL level designates very severe error events that will presumably lead the application to abort.
Nginx/Tomcat
严格的来说,/Nginx 应该叫做HTTP Server,而 Tomcat 则是一个Application Server,或者更准确的来说,是一个Servlet/JSP应用的容器 HTTP Server 关心的是 HTTP 协议层面的传输和访问控制,所以在 Nginx 上你可以看到代理、负载均衡等功能。 客户端通过 HTTP Server 访问服务器上存储的资源(HTML 文件、图片文件等等),通过 CGI 技术,也可以将处理过的内容通过 HTTP Server 分发,但是一个 HTTP Server 始终 只是把服务器上的文件如实的通过 HTTP 协议传输给客户端。 而应用服务器,则是一个应用执行的容器,它首先需要支持开发语言的 Runtime(对于 Tomcat 来说,就是 Java),保证应用能够在应用服务器上正常运行。 其次,需要支持应用相关的规范,例如类库、安全方面的特性。对于 Tomcat 来说,就是需要提供 JSP/Sevlet 运行需要的标准类库、Interface 等。 为了方便,应用服务器往往也会集成 HTTP Server 的功能,但是不如专业的 HTTP Server 那么强大,所以应用服务器往往是运行在 HTTP Server 的背后,执行应用,将动态的内容转化为静态的内容 之后,通过 HTTP Server 分发到客户端。
什么情况下回出现Full GC,什么情况下会出现Young GC
- 对象优先在新生代Eden区中分配,如果Eden区没有足够的空间时,就会触发一次young gc
- Full gc的触发条件有多个,FULL GC的时候会STOP THE WORD。
- 在执行Young gc之前,JVM会进行空间分配担保——如果老年代的连续空间小于新生代对象的总大小(或历次晋升的平均大小),则触发一次full gc。
- 显式调用System.gc()方法时;
- 大对象直接进入老年代,从年轻代晋升上来的老对象,尝试在老年代分配内存时,但是老年代内存空间不够;
关键字
- synchronized 使用synchronized关键字会以加锁的方式解决不同步问题
- volatile 使用volatile修饰的变量无需使用数据副本进行操作而是直接使用数据,因此不会造成不同步的现象
异常最佳实践
- 在Finally块中清理资源或者使用try-with-resource语句
- 指定具体的异常
- 对异常进行文档说明
- 抛出异常的时候包含描述信息
- 首先捕获最具体的异常
- 不要捕获Throwable
- 不要忽略异常
- 不要记录并抛出异常
- 包装异常时不要抛弃原始的异常