在 Ubuntu 中安装 Jenkins

Jenkins 是目前流行的 CI 平台,终于得闲,便想到试用看看,略作笔记。

官方文档: https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Ubuntu

Jenkins 依赖于 JDK 和 JRE,可以通过以下代码安装。

安装完成后,继续安装 Jenkins 本身。

Jenkins 的默认端口为 8080,在安装完成后即可使用。

 

常见 Java 框架、库与工具简介

本文将不定期更新一些常见的 Java 框架与库,或是简单的介绍与感想。

框架

  • Spring – 文档与实例丰富;适合大中型系统
  • Play Framework – 轻量;适合 RESTful;源代码修改后无需重启编译器与服务器;内置 JSON 库
  • Dropwizard

服务器(Server)

IDE

标准 API

模板引擎(Template engine)

数据库(Database)

对象映射工具(Object mapping)

测试工具(Testing)

日志工具(Logging)

库(Library)

编译工具(Build tool)

其他工具

JVM 语言

参考链接:Awesome Java

初版条目的分类选取引用于 disc99 的博客文章《Javaを使うなら知っておきたい技術、フレームワーク、ライブラリ、ツールまとめ》。

SOAP 与 REST 简单比较

SOAP
SOAP是一种协议。
SOAP是Simple Object Access Protocol的缩写,用于传输小规模数据。SOAP消息为XML格式,通常以HTTP协议发送(亦通过TCP/IP)。
由于采用了XML格式,SOAP需要定义数据的类型与功能。如果要传输二进制数据,则必须先以base64格式对其编码。WSDL、XSDs、WS-Addressing等协议或技术都与之相关。
SOAP由于可以同时控制服务器与客户端的行为,因此经常被用于内部网络API。

REST
REST是一种传输架构,与协议无关。
REST是Representational State Transfer的缩写,可以较为灵活地在客户端与服务器之间传输数据,格式可以是JSON、XML甚至纯文本,机制较SOAP更为轻量。
REST采用通常的HTTP方法(如HTTP GET、HTTP PUT等)传输,而无需借助XML。只要框架支持HTTP,就能实现REST。二进制数据也可以通过请求传输。不过需要注意,REST并没有与CRUD方法一一对应。
REST由于简单轻量,且格式更为灵活,不少公网API都采用了这种方式。

在选择SOAP还是REST时,可以考虑以下几点:

REST的优势:

  • 实现简单
  • 学习曲线平缓
  • 传输效率更高(无需定义XML)
  • 传输速度更快(没有引入额外的处理)
  • 与其他一些网络技术在设计理念上有共通之处

REST的劣势:

  • 是否需要独立于平台、框架或协议(REST依赖HTTP)
  • 是否需要在分布式企业环境中运作(REST是直接的点对点通信)
  • 是否需要限定传输格式
  • 是否需要使用WS标准提供的扩展功能(如项目已有的代码或接口)
  • 是否需要利用内建的错误处理机制
  • 是否希望利用语言或框架自带的自动化机制来创建接口

Java 非访问修饰符简述

 

abstract

用于定义抽象方法。抽象方法仅具有签名(方法名、参数与返回值),需进一步覆盖使用。包含抽象方法的类称为抽象类,同样需要添加 abstract 修饰符。继承抽象类时必须覆盖其中所有的抽象方法。interface 指令也起到了抽象的功能,因此常省略重复使用 abstract。

 

static

用于定义静态成员(字段或方法)。静态成员无需实例化即可访问。

 

final

final 方法无法覆盖、final 字段无法再次赋值、final 类无法被继承。

 

transient

transient 对象不会被序列化。有时,为了将对象通过网络传输或存入数据库,需要将序列化(如将其转换为字节数组形式)。对于一些临时变量,或其他一些特殊原因,可通过 transient 修饰符是成员免于序列化。

 

volatile

多线程处理中,各线程的成员将各自分配缓存。volatile 修饰符强制所有线程中的成员共用同一缓存,共享相同的值。

 

synchronized

synchronized 修饰符使成员无法被多个线程同时访问,必须依次进行(同步处理)。如果方法分属不同实例,synchronized 将无法确保处理同步。

 

native

native 修饰符表示方法由非 Java 语言实现,因此,方法体将被省略。随着 Java 性能的改善,native 的应用范围也逐渐缩小。

 

strictfp

strictfp 修饰符要求程序严格遵循 IEEE 754 标准对浮点小数进行计算。此时,不同环境中浮点数运算的误差不复存在,但处理速度将有所下降。

Java 的内存大小与垃圾回收简述

一些 Java 程序在高负荷时性能会出现显著下降。一个可能的原因是没有设定恰当的内存大小(memory sizing),导致垃圾回收(Garbage collection,下称 GC)频繁执行。即使 CPU 满负荷运作,性能依然较差。

JVM 的内存分 Java 专用区域与 C Heap 两部分,其中前者又分为维护 Java 对象的 Java Heap 区域与维护类信息的 Permanent 区域。一些采用了分代收集机制(Generational Garbage Collection,或称 Generation Scavenging)的 GC 系统还将 Java Heap 进一步细分为 Eden、Survivor 与 Old 区域。Eden 维护生成的对象,GC 时未被回收的对象将被移入 Survivor,长期存在的对象进一步进入 Old 区域。

对于分代收集,GC 可分为 Full GC 与 Copy GC,其中,Copy GC 仅针对 New 区域(Eden+Survivor),Full GC 则针对所有区域。为防止 GC 过于频繁,我们需要设置合适的内存大小。常见的情况有以下这些:

Copy GC

  • Eden 区域空间不足

Full GC

  • Eden 区域空间不足时,Old 区域的可用内存大小不足以容纳 New 区域的已使用内存
  • New 区域与 Old 区域的可用内存空间不足
  • GC 后 Old 区域的剩余空间过低
  • GC 后 Old 区域的空间增加
  • Permanent 区域的可用空间不足

在程序执行过程中,Permanent 区域很少发生变化,因此我们因主要考虑 Full GC 的前两种情况。未避免 Old 区域的空间增加,建议将 Java Heap 的初始值与最大值设为同一值。

通常,Full GC 更为耗时,因此我们应主要考虑减少 Full GC,令 Copy GC 可以解决大部分回收。为此,Old 区域的内存大小是一个关键。

Old 区域的内存大小应与 Java 程序占用内存、Java 服务器占用内存,及 New 区域的内存大小,之和,相当。

举例来说,对于 Web 程序,事务处理占用的内存可以被立即释放,会话占用的内存则需要长期保存。因此后者应归为 Java 程序占用内存。

New 区域的内存大小也需要专门考虑,尤其是 Survivor 区域的大小十分重要。如果 Survivor 区域的内存大小不足,对象就需要被移动至 Old 区域。如果这些对象的生存周期不够长,就会进一步引发 Full GC。增加 Survivor 区域可以缓解该问题。然而,如果 Survivor 区域过大,Copy GC 的处理时间就会增加。因此,应当设置一个阀值,将经历 Copy GC 次数超过该值的对象移植 Old 区域。应尽可能避免 Survivor 区域已满,对象从 Eden 区域直接被移动至 Ole 区域的情况。为此,需要在 Copy GC 发生后检查 Survivor 区域是否被完全占用,以及移动至 Old 区域的对象年龄(生存次数)是否合适。如有可能,应为 Survivor 区域分配较大的内存大小,以适应需求。具体的内存大小估算方式,可以查找其他相关文章。

Eden 区域的内存大小将直接影响 Copy GC 的频率。通常,每发生 10-20 次 Copy GC 后执行一次 Full GC 较为合适。

Documentum 上传大尺寸文件

说明:

Documentum API (DFC) 提供了多种文件上传方法,如果需要上传的文件较大,则需要选择合适的方法。

其中,SetContent()及相关扩展方法需要使用 Byte 数组构造文件内容,因此会消耗较多内存,抛出 java.lang.OutOfMemoryError: Java heap space 异常。可以通过配置 JRE 的 Xms 参数(例:-vmargs -Xmx1024M 表示为 JVM 分配最少1024MB内存)增加内存分配以在一定程度上缓解该问题,但如果系统内存不足,将无法启动程序。

另一方面,SetFile()及相关扩展方法可以接收文件路径,无需将整个文件载入内存,但却需要耗费额外存储空间。应记得在完成处理后删除临时文件。

顺便一提,造成 heap space 不足通常可能有以下原因:线程过多、 java.io.File 类的 deleteOnExit() 方法维护的文件信息过多、大量 I/O 操作、java.util.zip 包的 Deflater 与 Inflater 类的构造函数在 end() 方法被调用前保存了大量信息、java.nio.ByteBuffer 类的 allocateDirect() 或 java.nio.channels.FileChannel类的 map() 方法生成了大量 Buffer 对象实例。

Java 开发笔记

作为分类目录的一个补充,在这里按照功能类别对 Java 开发中的一点心得和笔记作一个索引。其中部分是根据自己在查找网络资料时找到的内容的整理与演绎,在此感谢所有那些无私分享经验的人们。

基本

线程

垃圾回收

其他

基于 Eclipse + Tomcat 的 Java Servlet Web 开发环境搭建与配置

2014年8月26日更新

本文应用的软件环境

  • Windows 8.1 Pro (64bit)
  • Eclipse IDE for Java EE Developers (Ver.4.4 Luna)
  • Tomcat 8.0.9
  • Java 7 Update 55 (64bit)

概览

  • 安装 Eclipse
  • 安装 Tomcat
  • 安装 JDK
  • 新建 HelloWorld Servlet

安装 Eclipse

从 http://www.eclipse.org/downloads/ 下载包含了 WTP (Web Tools Platform)的 Eclipse IDE for Java EE Developers。将下载得到的压缩包解压至任意路径。

安装 Tomcat

从 http://tomcat.apache.org/ 下载 Binary Distributions – Core – zip 文件。将下载得到的压缩包解压至任意路径。

安装 JDK

从 http://www.oracle.com/technetwork/java/javase/downloads/ 下载 JDK 并根据提示安装。

新建 HelloWorld Servlet

启动 Eclipse。

从菜单选择 File – New – Project – Web – Dynamic Web Project。

填写任意 [Project Name],此处采用 TomcatTest。选择 [New Runtime] – [Apache – Apache Tomcat v8.0] – [Create a new local server] – [Next]。

[Browse] 至 Tomcat 的解压路径。

在之后的 Web Module 页面勾选 [Generate web.xml deployment descriptor]。

点击 [Finish] 完成配置。

右键单击 workspace 中列出的项目 TomcatTest,选择 [Properties] – [Resource] – [Text file encoding] – [Other] – [UTF-8] 以避免字符编码问题。

单击 workspace 中列出的项目 TomcatTest,从菜单选择 [File] – [New] – [Other] – [Web] – [Servlet]。填写任意 [Class Name] (此处采用 HelloWorld)与 [Java Package]。

在新建的 HelloWorld.java 中的 doGet 方法中添加如下语句:

response.getWriter().write(“Hello, World!”);

在 Eclipse 的 Servers 标签页中右键单击先前创建的 Tomcat v8.0,选择 [Add and remove],将 TomcatTest 项目从 Available 栏移动至 Configured 栏。点击 [Finish]。

右键单击 Servers 标签页的 Tomcat v8.0,选择 [Start] 启动。

在浏览器中输入 http://localhost:8080/TomcatTest/HelloWorld 以确认 Tomcat 是否正常运行。页面应显示文字“Hello World!”。

对 TomcatTest 项目的 WebContent 文件夹右键单击,选择 [New] – [Other] – [Web] – [JSP File]。之后可以在浏览器中测试访问该页面。