Java 8 简明教程

2014年3月29日 由 acefarmer 没有评论 »
欢迎阅读我编写的Java 8介绍。本教程将带领你一步一步地认识这门语言的新特性。通过简单明了的代码示例,你将会学习到如何使用默认接口方法,Lambda表达式,方法引用和重复注解。看完这篇教程后,你还将对最新推出的API有一定的了解,例如:流控制,函数式接口,map扩展和新的时间日期API等等。

允许在接口中有默认方法实现

Java 8 允许我们使用default关键字,为接口声明添加非抽象的方法实现。这个特性又被称为扩展方法。下面是我们的第一个例子:

Java代码
  1. interface Formula {
  2.     double calculate(int a);
  3.     default double sqrt(int a) {
  4.         return Math.sqrt(a);
  5.     }
  6. }

在接口Formula中,除了抽象方法caculate以外,还定义了一个默认方法sqrt。Formula的实现类只需要实现抽象方法caculate就可以了。默认方法sqrt可以直接使用。

Java代码
  1. Formula formula = new Formula() {
  2.     @Override
  3.     public double calculate(int a) {
  4.         return sqrt(a * 100);
  5.     }
  6. };
  7. formula.calculate(100);     // 100.0
  8. formula.sqrt(16);           // 4.0

formula对象以匿名对象的形式实现了Formula接口。代码很啰嗦:用了6行代码才实现了一个简单的计算功能:a*100开平方根。我们在下一节会看到,Java 8 还有一种更加优美的方法,能够实现包含单个函数的对象。

Lambda表达式

让我们从最简单的例子开始,来学习如何对一个string列表进行排序。我们首先使用Java 8之前的方法来实现:

Java代码
  1. List<String> names = Arrays.asList(“peter”, ”anna”, ”mike”, ”xenia”);
  2. Collections.sort(names, new Comparator<String>() {
  3.     @Override
  4.     public int compare(String a, String b) {
  5.         return b.compareTo(a);
  6.     }
  7. });

静态工具方法Collections.sort接受一个list,和一个Comparator接口作为输入参数,Comparator的实现类可以对输入的list中的元素进行比较。通常情况下,你可以直接用创建匿名Comparator对象,并把它作为参数传递给sort方法。

除了创建匿名对象以外,Java 8 还提供了一种更简洁的方式,Lambda表达式。

Java代码
  1. Collections.sort(names, (String a, String b) -> {
  2.     return b.compareTo(a);
  3. });

你可以看到,这段代码就比之前的更加简短和易读。但是,它还可以更加简短:

Java代码
  1. Collections.sort(names, (String a, String b) -> b.compareTo(a));

只要一行代码,包含了方法体。你甚至可以连大括号对{}和return关键字都省略不要。不过这还不是最短的写法:

Java代码
  1. Collections.sort(names, (a, b) -> b.compareTo(a));

Java编译器能够自动识别参数的类型,所以你就可以省略掉类型不写。让我们再深入地研究一下lambda表达式的威力吧。

函数式接口

Lambda表达式如何匹配Java的类型系统?每一个lambda都能够通过一个特定的接口,与一个给定的类型进行匹配。一个所谓的函数式接口必须要有且仅有一个抽象方法声明。每个与之对应的lambda表达式必须要与抽象方法的声明相匹配。由于默认方法不是抽象的,因此你可以在你的函数式接口里任意添加默认方法。任意只包含一个抽象方法的接口,我们都可以用来做成lambda表达式。为了让你定义的接口满足要求,你应当在接口前加上@FunctionalInterface 标注。编译器会注意到这个标注,如果你的接口中定义了第二个抽象方法的话,编译器会抛出异常。举例:

Java代码
  1. @FunctionalInterface
  2. interface Converter<F, T> {
  3.     T convert(F from);
  4. }
  5. Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
  6. Integer converted = converter.convert(“123″);
  7. System.out.println(converted);    // 123

注意,如果你不写@FunctionalInterface 标注,程序也是正确的。

方法和构造函数引用

上面的代码实例可以通过静态方法引用,使之更加简洁:

Java代码
  1. Converter<String, Integer> converter = Integer::valueOf;
  2. Integer converted = converter.convert(“123″);
  3. System.out.println(converted);   // 123

Java 8 允许你通过::关键字获取方法或者构造函数的的引用。上面的例子就演示了如何引用一个静态方法。而且,我们还可以对一个对象的方法进行引用:

Java代码
  1. class Something {
  2.     String startsWith(String s) {
  3.         return String.valueOf(s.charAt(0));
  4.     }
  5. }
  6. Something something = new Something();
  7. Converter<String, String> converter = something::startsWith;
  8. String converted = converter.convert(“Java”);
  9. System.out.println(converted);    // ”J”

让我们看看如何使用::关键字引用构造函数。首先我们定义一个示例bean,包含不同的构造方法:

Java代码
  1. class Person {
  2.     String firstName;
  3.     String lastName;
  4.     Person() {}
  5.     Person(String firstName, String lastName) {
  6.         this.firstName = firstName;
  7.         this.lastName = lastName;
  8.     }
  9. }

接下来,我们定义一个person工厂接口,用来创建新的person对象:

Java代码
  1. interface PersonFactory<P extends Person> {
  2.     P create(String firstName, String lastName);
  3. }

然后我们通过构造函数引用来把所有东西拼到一起,而不是像以前一样,通过手动实现一个工厂来这么做。

Java代码
  1. PersonFactory<Person> personFactory = Person::new;
  2. Person person = personFactory.create(“Peter”, ”Parker”);

我们通过Person::new来创建一个Person类构造函数的引用。Java编译器会自动地选择合适的构造函数来匹配PersonFactory.create函数的签名,并选择正确的构造函数形式。

Lambda的范围

对于lambdab表达式外部的变量,其访问权限的粒度与匿名对象的方式非常类似。你能够访问局部对应的外部区域的局部final变量,以及成员变量和静态变量。访问局部变量我们可以访问lambda表达式外部的final局部变量:

Java代码
  1. final int num = 1;
  2. Converter<Integer, String> stringConverter =
  3.         (from) -> String.valueOf(from + num);
  4. stringConverter.convert(2);     // 3

但是与匿名对象不同的是,变量num并不需要一定是final。下面的代码依然是合法的:

Java代码
  1. int num = 1;
  2. Converter<Integer, String> stringConverter =
  3.         (from) -> String.valueOf(from + num);
  4. stringConverter.convert(2);     // 3

然而,num在编译的时候被隐式地当做final变量来处理。下面的代码就不合法:

Java代码
  1. int num = 1;
  2. Converter<Integer, String> stringConverter =
  3.         (from) -> String.valueOf(from + num);
  4. num = 3;

在lambda表达式内部企图改变num的值也是不允许的。

访问成员变量和静态变量

与局部变量不同,我们在lambda表达式的内部能获取到对成员变量或静态变量的读写权。这种访问行为在匿名对象里是非常典型的。

Java代码
  1. class Lambda4 {
  2.     static int outerStaticNum;
  3.     int outerNum;
  4.     void testScopes() {
  5.         Converter<Integer, String> stringConverter1 = (from) -> {
  6.             outerNum = 23;
  7.             return String.valueOf(from);
  8.         };
  9.         Converter<Integer, String> stringConverter2 = (from) -> {
  10.             outerStaticNum = 72;
  11.             return String.valueOf(from);
  12.         };
  13.     }
  14. }

访问默认接口方法

还记得第一节里面formula的那个例子么? 接口Formula定义了一个默认的方法sqrt,该方法能够访问formula所有的对象实例,包括匿名对象。这个对lambda表达式来讲则无效。

默认方法无法在lambda表达式内部被访问。因此下面的代码是无法通过编译的:

Java代码
  1. Formula formula = (a) -> sqrt( a * 100);

内置函数式接口

JDK 1.8 API中包含了很多内置的函数式接口。有些是在以前版本的Java中大家耳熟能详的,例如Comparator接口,或者Runnable接口。对这些现成的接口进行实现,可以通过@FunctionalInterface 标注来启用Lambda功能支持。此外,Java 8 API 还提供了很多新的函数式接口,来降低程序员的工作负担。有些新的接口已经在Google Guava库中很有名了。如果你对这些库很熟的话,你甚至闭上眼睛都能够想到,这些接口在类库的实现过程中起了多么大的作用。Predicates

Predicate是一个布尔类型的函数,该函数只有一个输入参数。Predicate接口包含了多种默认方法,用于处理复杂的逻辑动词(and, or,negate):

Java代码
  1. Predicate<String> predicate = (s) -> s.length() > 0;
  2. predicate.test(“foo”);              // true
  3. predicate.negate().test(“foo”);     // false
  4. Predicate<Boolean> nonNull = Objects::nonNull;
  5. Predicate<Boolean> isNull = Objects::isNull;
  6. Predicate<String> isEmpty = String::isEmpty;
  7. Predicate<String> isNotEmpty = isEmpty.negate();

Functions

Function接口接收一个参数,并返回单一的结果。默认方法可以将多个函数串在一起(compse, andThen):

Java代码
  1. Function<String, Integer> toInteger = Integer::valueOf;
  2. Function<String, String> backToString = toInteger.andThen(String::valueOf);
  3. backToString.apply(“123″);     // ”123″

Suppliers

Supplier接口产生一个给定类型的结果。与Function不同的是,Supplier没有输入参数。

Java代码
  1. Supplier<Person> personSupplier = Person::new;
  2. personSupplier.get();   // new Person

Consumers

Consumer代表了在一个输入参数上需要进行的操作。

Java代码
  1. Consumer<Person> greeter = (p) -> System.out.println(“Hello, ” + p.firstName);
  2. greeter.accept(new Person(“Luke”, ”Skywalker”));

Comparators

Comparator接口在早期的Java版本中非常著名。Java 8 为这个接口添加了不同的默认方法。

Java代码
  1. Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
  2. Person p1 = new Person(“John”, ”Doe”);
  3. Person p2 = new Person(“Alice”, ”Wonderland”);
  4. comparator.compare(p1, p2);             // > 0
  5. comparator.reversed().compare(p1, p2);  // < 0

Optionals

Optional不是一个函数式接口,而是一个精巧的工具接口,用来防止NullPointerEception产生。这个概念在下一节会显得很重要,所以我们在这里快速地浏览一下Optional的工作原理。

Optional是一个简单的值容器,这个值可以是null,也可以是non-null。考虑到一个方法可能会返回一个non-null的值,也可能返回一个空值。为了不直接返回null,我们在Java 8中就返回一个Optional。

Java代码
  1. Optional<String> optional = Optional.of(“bam”);
  2. optional.isPresent();           // true
  3. optional.get();                 // ”bam”
  4. optional.orElse(“fallback”);    /%2

lsof 命令

2014年3月3日 由 acefarmer 没有评论 »

1, 使用 lsof 命令行列出所有打开的文件

# lsof 

这可是一个很长的列表,包括打开的文件和网络

lsof1

上述屏幕截图中包含很多列,例如 PID、user、FD 和 TYPE 等等。

FD - File descriptor

FD 列包含这样一些值

cwd - Current working directory
txt - Text file
mem - Memory Mapped file
mmap - Memory Mapped device
Number - It represent the actual file descriptor. For example, 0u, 1w and 3r

r 是读的意思,w 是写,u 代表读写

Type 代表文件类型,例如:

>REG - Regular file 
>DIR - Directory
>CHR - Character special file
>FIFO - First in first out

2, 列出某个用户打开的文件

# lsof -u user_name 

Example:

# lsof -u crybit
COMMAND   PID   USER   FD   TYPE             DEVICE SIZE/OFF       NODE NAME
sshd    29609 crybit  cwd    DIR            144,233     4096  117711421 /
sshd    29609 crybit  rtd    DIR            144,233     4096  117711421 /
sshd    29609 crybit  txt    REG            144,233   409488  119020186 /usr/sbin/sshd
sshd    29609 crybit  mem    REG            144,241          2443001619 (deleted)/dev/zero (stat: No such file or directory)
sshd    29609 crybit  mem    REG               8,37           119021850 /lib64/libnss_dns-2.5.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119021984 /lib64/security/pam_succeed_if.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119022000 /lib64/security/pam_limits.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119021960 /lib64/security/pam_keyinit.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119021972 /lib64/security/pam_cracklib.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119021987 /lib64/security/pam_nologin.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119021988 /lib64/security/pam_deny.so (path dev=144,233)
sshd    29609 crybit  mem    REG               8,37           119019223 /usr/lib64/libcrack.so.2.8.0 (path dev=144,233)
.....
.....

3, 列出在某个端口运行的进程

# lsof -i :port_number 

Example:

# lsof -i :22
COMMAND   PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
sshd      769   root    3u  IPv6 2281738844      0t0  TCP *:ssh (LISTEN)
sshd      769   root    4u  IPv4 2281738846      0t0  TCP *:ssh (LISTEN)
# lsof -i :3306
COMMAND   PID  USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
mysqld  11106 mysql   10u  IPv4 2340975114      0t0  TCP *:mysql (LISTEN)

4, 只列出使用 IPv4 的打开文件

# lsof -i 4 - For IPv4 

Example:

# lsof -i 4
COMMAND     PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
sshd        769   root    4u  IPv4 2281738846      0t0  TCP *:ssh (LISTEN)
named      8362  named   20u  IPv4 2334751017      0t0  TCP localhost.localdomain:domain (LISTEN)
named      8362  named   21u  IPv4 2334751019      0t0  TCP crybit.com:domain (LISTEN)
named      8362  named   22u  IPv4 2334751021      0t0  TCP localhost.localdomain:rndc (LISTEN)
named      8362  named  512u  IPv4 2334751016      0t0  UDP localhost.localdomain:domain 
named      8362  named  513u  IPv4 2334751018      0t0  UDP crybit.com:domain 
tcpserver  9975   root    3u  IPv4 2335487959      0t0  TCP *:pop3 (LISTEN)
tcpserver  9978   root    3u  IPv4 2335487967      0t0  TCP *:pop3s (LISTEN)
tcpserver  9983   root    3u  IPv4 2335487997      0t0  TCP *:imap (LISTEN)
tcpserver  9987   root    3u  IPv4 2335488014      0t0  TCP *:imaps (LISTEN)
xinetd    10413   root    5u  IPv4 2336070983      0t0  TCP *:ftp (LISTEN)
xinetd    10413   root    6u  IPv4 2336070984      0t0  TCP *:smtp (LISTEN)
mysqld    11106  mysql   10u  IPv4 2340975114      0t0  TCP *:mysql (LISTEN)
# lsof -i 6 

Example:

# lsof -i 6
COMMAND   PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
sshd      769   root    3u  IPv6 2281738844      0t0  TCP *:ssh (LISTEN)
named    8362  named   23u  IPv6 2334751024      0t0  TCP localhost.localdomain:rndc (LISTEN)
httpd   29241   root    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)
httpd   29241   root    6u  IPv6 2439777211      0t0  TCP *:https (LISTEN)
httpd   29243 apache    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)
httpd   29243 apache    6u  IPv6 2439777211      0t0  TCP *:https (LISTEN)
httpd   29244 apache    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)
httpd   29244 apache    6u  IPv6 2439777211      0t0  TCP *:https (LISTEN)
httpd   29245 apache    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)
httpd   29245 apache    6u  IPv6 2439777211      0t0  TCP *:https (LISTEN)
httpd   29246 apache    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)

5, 列出端口在 1-1024 之间的所有进程

# lsof -i :1-1024 

Example:

# lsof -i :1-1024
COMMAND     PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
sshd        769   root    3u  IPv6 2281738844      0t0  TCP *:ssh (LISTEN)
sshd        769   root    4u  IPv4 2281738846      0t0  TCP *:ssh (LISTEN)
named      8362  named   20u  IPv4 2334751017      0t0  TCP localhost.localdomain:domain (LISTEN)
named      8362  named   21u  IPv4 2334751019      0t0  TCP crybit.com:domain (LISTEN)
named      8362  named   22u  IPv4 2334751021      0t0  TCP localhost.localdomain:rndc (LISTEN)
named      8362  named   23u  IPv6 2334751024      0t0  TCP localhost.localdomain:rndc (LISTEN)
tcpserver  9975   root    3u  IPv4 2335487959      0t0  TCP *:pop3 (LISTEN)
tcpserver  9978   root    3u  IPv4 2335487967      0t0  TCP *:pop3s (LISTEN)
tcpserver  9983   root    3u  IPv4 2335487997      0t0  TCP *:imap (LISTEN)
tcpserver  9987   root    3u  IPv4 2335488014      0t0  TCP *:imaps (LISTEN)
xinetd    10413   root    5u  IPv4 2336070983      0t0  TCP *:ftp (LISTEN)
xinetd    10413   root    6u  IPv4 2336070984      0t0  TCP *:smtp (LISTEN)
httpd     29241   root    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)
httpd     29241   root    6u  IPv6 2439777211      0t0  TCP *:https (LISTEN)
httpd     29243 apache    4u  IPv6 2439777206      0t0  TCP *:http (LISTEN)
....
....

6, 根据进程id来列出打开的文件

# lsof -p PID

Example:

# lsof -p 11106
COMMAND   PID  USER   FD   TYPE             DEVICE SIZE/OFF       NODE NAME
mysqld  11106 mysql  cwd    DIR            144,233     4096  119025114 /var/lib/mysql
mysqld  11106 mysql  rtd    DIR            144,233     4096  117711421 /
mysqld  11106 mysql  txt    REG            144,233  9484782  119025094 /usr/libexec/mysqld
mysqld  11106 mysql  mem    REG               8,37           119025094 /usr/libexec/mysqld (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119021850 /lib64/libnss_dns-2.5.so (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119021830 /lib64/libnss_files-2.5.so (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119021841 /lib64/libsepol.so.1 (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119021801 /lib64/libselinux.so.1 (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119021785 /lib64/libresolv-2.5.so (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119021920 /lib64/libkeyutils-1.2.so (path dev=144,233)
mysqld  11106 mysql  mem    REG               8,37           119017006 /usr/lib64/libkrb5support.so.0.1 (path dev=144,233)
....
....

7, 杀掉某个用户的所有活动进程

# killall -9 `lsof -t -u username` 

8, 列出某个目录中被打开的文件

# lsof +D path_of_the_directory 

Example:

# lsof +D /var/log/
COMMAND     PID   USER   FD   TYPE  DEVICE SIZE/OFF      NODE NAME
syslogd    9729   root    1w   REG 144,233        0 119019158 /var/log/kernel
syslogd    9729   root    2w   REG 144,233   350722 119021699 /var/log/messages
syslogd    9729   root    3w   REG 144,233   591577 119019159 /var/log/secure
syslogd    9729   root    4w   REG 144,233   591577 119019159 /var/log/secure

9, 根据进程名称列出打开的文件

# lsof -c process_name 

Example:

# lsof -c ssh
COMMAND     PID USER   FD   TYPE     DEVICE SIZE/OFF    NODE NAME
sshd        483 root  cwd    DIR        8,9     4096       2 /
sshd        483 root  rtd    DIR        8,9     4096       2 /
sshd        483 root  txt    REG        8,9   523488 1193409 /usr/sbin/sshd

10, 列出所有网络连接

# lsof -i 

该命令列出所有侦听和已建立的网络连接
Example:

# lsof -i
COMMAND     PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
sshd        769   root    3u  IPv6 2281738844      0t0  TCP *:ssh (LISTEN)
sshd        769   root    4u  IPv4 2281738846      0t0  TCP *:ssh (LISTEN)
named      8362  named   20u  IPv4 2334751017      0t0  TCP localhost.localdomain:domain (LISTEN)
named      8362  named   21u  IPv4 2334751019      0t0  TCP crybit.com:domain (LISTEN)
named      8362  named   22u  IPv4 2334751021      0t0  TCP localhost.localdomain:rndc (LISTEN)
named      8362  named   23u  IPv6 2334751024      0t0  TCP localhost.localdomain:rndc (LISTEN)
named      8362  named  512u  IPv4 2334751016      0t0  UDP localhost.localdomain:domain



转自 http://flycars001.iteye.com/blog/2024783

Java中何时定义方法为静态的

2014年3月1日 由 acefarmer 没有评论 »

One rule-of-thumb: ask yourself “does it make sense to call this method, even if no Obj has been constructed yet?” If so, it should definitely be static.

So in a class Car you might have a method double convertMpgToKpl(double mpg) which would be static, because one might want to know what 35mpg converts to, even if nobody has ever built a Car. But void setMileage(double mpg) (which sets the efficiency of one particular Car) can’t be static since it’s inconceivable to call the method before any Car has been constructed.

(Btw, the converse isn’t always true: you might sometimes have a method which involves two Car objects, and still want it to be static. E.g. Car theMoreEfficientOf( Car c1, Car c2 ). Although this could be converted to a non-static version, some would argue that since there isn’t a “privileged” choice of which Car is more important, you shouldn’t force a caller to choose one Car as the object you’ll invoke the method on. This situation accounts for a fairly small fraction of all static methods, though.)

 

 

A few good examples here. I would add, however, that “static” is often valuable when you know something is not going to change across instances. If this is the case, I would really consider the “Single Responsability Principle”, which implies a class should have one responsability and thus only one reason to change. I feel one should consider moving the “ConvertMpgToKpl(double mpg)” function, and similar methods, to their own class. The purpose of a car object is to allow instantiation of cars, not provide a comparison between them. Those should be external to the class.

 

Define static methods in the following scenarios only:

  1. If you are writing utility classes and they are not supposed to be changed.
  2. If the method is not using any instance variable.
  3. If any operation is not dependent on instance creation.
  4. If there is some code that can easily be shared by all the instance methods, extract that code into a static method.
  5. If you are sure that the definition of the method will never be changed or overridden. As static methods can not be overridden.

 

After reading Misko’s articles I believe that static methods are bad from a testing point of view. You should havefactories instead(maybe using a dependency injection tool like Guice).

how do I ensure that I only have one of something

only have one of something The problem of “how do I ensure that I only have one of something” is nicely sidestepped. You instantiate only a single ApplicationFactory in your main, and as a result, you only instantiate a single instance of all of your singletons.

The basic issue with static methods is they are procedural code

The basic issue with static methods is they are procedural code. I have no idea how to unit-test procedural code. Unit-testing assumes that I can instantiate a piece of my application in isolation. During the instantiation I wire the dependencies with mocks/friendlies which replace the real dependencies. With procedural programing there is nothing to “wire” since there are no objects, the code and data are separate.

There are some valid reasons to use static methods:

  • Performance: if you want some code to be run, and don’t want to instantiate an extra object to do so, shove it into a static method. The JVM also can optimize static methods a lot (I read once James Gosling declaring that you don’t need custom instructions in the JVM, since static methods will be just as fast, but couldn’t find the source). Yes, it is micro-optimization, and probably unneeded. And we programmers never do unneeded things just because they are cool, right?
  • Practicality: instead of calling new Util().method(arg), call Util.method(arg), or method(arg)with static imports. Easier, shorter.
  • Adding methods: you really wanted the class String to have a removeSpecialChars() instance method, but it’s not there (and it shouldn’t, since your project’s special characters may be different from the other project’s), and you can’t add it (since Java is minimally sane), so you create an utility class, and call removeSpecialChars(s) instead of s.removeSpecialChars(). Sweet.
  • Purity: taking some precautions, your static method will be a pure function, that is, the only thing it depends on is its parameters. Data in, data out. This is easier to read and debug, since you don’t have inheritance quirks to worry about. You can do it with instance methods too, but the compiler will help you a little more with static methods (by not allowing references to instance attributes, overriding methods, etc.).

You’ll also have to create a static method if you want to make a singleton, but… don’t. I mean, think twice.

Now, more importantly, why you wouldn’t want to create a static method? Basically, polymorphism goes out of the window. You’ll not be able to override the method, nor declare it in an interface. It takes a lot of flexibility out from your design. Also, if you need state, you’ll end up with lots of concurrency bugs and/or bottlenecks if you are not careful.

An even more interesting discussion is about static inner classes, but that is for another time :)

恭贺spark成为apache顶级项目

2014年3月1日 由 acefarmer 没有评论 »

 

Apache软件基金会今天宣布,Spark成为Apache软件基金会的一个顶级项目

 

http://spark.apache.org/

localhost与127.0.0.1区别

2014年2月17日 由 acefarmer 没有评论 »

1: localhost也叫local ,正确的解释是:本地服务器,localhot(local)是不经网卡传输!这点很重要,它不受网络防火墙和网卡相关的的限制。

2: 127.0.0.1在windows等系统的正确解释是:本机地址(本机服务器)    127.0.0.1是通过网卡传输,依赖网卡,并受到网络防火墙和网卡相关的限制。   一般设置程序时本地服务用localhost是最好的,localhost不会解析成ip,也不会占用网卡、网络资源。   有时候用localhost可以,但用127.0.0.1就不可以的情况就是在于此。猜想localhost访问时,系统带的本机当前用户的权限去访问,而用ip的时候,等于本机是通过网络再去访问本机,可能涉及到网络用户的权限。

大陆开源软件镜像服务站点列表

2014年1月1日 由 acefarmer 没有评论 »

七牛云存储同步工具qrsync

2013年12月22日 由 acefarmer 没有评论 »

详细文档见其官方网站http://docs.qiniu.com/tools/v6/qrsync.html

这里只是做个示范,

bucket,是你在七牛注册的空间名

{
“access_key”:”your key”,
“secret_key”:”your key”,
“bucket”:”acefarmer”,
“sync_dir”:”F:/website/acefarmer.com/”,
“ignore_patterns”:”*.php”,
“debug_level”:1
}

 

cd 到qrsync.exe目录

 

qrsync.exe conf.json

 

java中的NULL

2013年11月24日 由 acefarmer 没有评论 »

一、null是代表不确定的对象

Java中,null是一个关键字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型变量。

比如:int a = null;是错误的。Ojbect o = null是正确的。

Java中,变量的适用都遵循一个原则,先定义,并且初始化后,才可以使用。我们不能int a后,不给a指定值,就去打印a的值。这条对对于引用类型变量也是适用的。

有时候,我们定义一个引用类型变量,在刚开始的时候,无法给出一个确定的值,但是不指定值,程序可能会在try语句块中初始化值。这时候,我们下面使用变量的时候就会报错。这时候,可以先给变量指定一个null值,问题就解决了。例如:

Connection conn = null;
try {
conn = DriverManager.getConnection(“url”, “user”, “password”);
} catch (SQLException e) {
e.printStackTrace();
}

String catalog = conn.getCatalog();
如果刚开始的时候不指定conn = null,则最后一句就会报错。

二、null本身不是对象,也不是Objcet的实例

null本身虽然能代表一个不确定的对象,但就null本身来说,它不是对象,也不知道什么类型,也不是java.lang.Object的实例。
可以做一个简单的例子:

//null是对象吗? 属于Object类型吗?
if (null instanceof java.lang.Object) {
System.out.println(“null属于java.lang.Object类型”);
} else {
System.out.println(“null不属于java.lang.Object类型”);
}
结果会输出:null不属于java.lang.Object类型

三、Java默认给变量赋值

在定义变量的时候,如果定义后没有给变量赋值,则Java在运行时会自动给变量赋值。赋值原则是整数类型int、byte、short、long的自动赋值为0,带小数点的float、double自动赋值为0.0,boolean的自动赋值为false,其他各供引用类型变量自动赋值为null。
这个具体可以通过调试来看。

四、容器类型与null

List:允许重复元素,可以加入任意多个null。

Set:不允许重复元素,最多可以加入一个null。

Map:Map的key最多可以加入一个null,value字段没有限制。

数组:基本类型数组,定义后,如果不给定初始值,则java运行时会自动给定值。引用类型数组,不给定初始值,则所有的元素值为null。

五、null的其他作用

1、判断一个引用类型数据是否null。 用==来判断。

2、释放内存,让一个非null的引用类型变量指向null。这样这个对象就不再被任何对象应用了。等待JVM垃圾回收机制去回收。

 

jmap jhat

2013年11月20日 由 acefarmer 没有评论 »

good tools to use

自定义网页字体

2013年10月9日 由 acefarmer 没有评论 »

在自定义这个博客主题过程中使用了某些特定字体,这些字体并非操作系统的内置字体,这样用户在浏览页面的时就有可能看不到设计时效果,导致页面显示很丑陋,一般的解决办法是把文字体成图片。

但是有点麻烦, 不适合我的样的懒人,而且做成图片也不方便修改.还有一种是通过CSS样式定义,我选择了这种, 因为它简单易用.CSS中使用@font-face属性来实现在网页中嵌入任意字体,稍稍复杂一点的问题是每种浏览器都有自己的字体格式要求。

.TTF或.OTF 适用于Firefox 3.5、Safari、Opera
.EOT 适用于Internet Explorer 4.0+
.SVG 适用于Chrome、IPhone

那么为了主流的浏览器们都能正常显示必须将字体转换为以上这些格式才行,

但是这样就违背了”懒人原则”.

[当girl手中的一支棒棒糖就快被抢走时,一只hero出现了! "放开那个girl!".. ]

恩, 我们的hero也没有迟到 http://www.fontsquirrel.com/fontface

该网站有很多别人制作完成的字体(适用于主流浏览器们的),

选择任意一款下载后你会得到一年压缩包,

解压后通常会得到*.eot,*.svg,*.ttf,*.woff和stylesheet.css等文件,

其中*.eot,*.svg,*.ttf,*.woff为字体文件,

放到自己站点的域空间内。

stylesheet.css为样式定义(也就是自定义字体部分),

@font-face {

font-family: ‘fontName’; /* 字体名称,可自己定义 */

src: url(‘fontName.eot’);

src: local(‘fontName Regular’),

local(‘fontName’),

url(‘fontName.woff’) format(‘woff’),

url(‘fontName.ttf’) format(‘truetype’),

url(‘fontName.svg#fontName’) format(‘svg’);

}

将其内容复制到自己的样式表中就可以了, (注意URL部分与自己域空间内字体文件路径相匹配)

如果要制作自己的字体也可以, http://www.fontsquirrel.com/fontface/generator

但貌似是收费的.. -_-!

http://www.cnblogs.com/mix-up/archive/2009/12/30/1636265.html

jquery的checked以及disabled

2013年10月9日 由 acefarmer 没有评论 »

下面只提到checked,其实disabled在jquery里的用法和checked是一模一样的

下边两种写法没有任何区别 只是少了些代码而已…

———————————————————–
<input id=”cb1″ type=”checkbox” checked />
<input id=”cb2″ type=”checkbox” checked=”checked” />

————————————————————–

jquery判断checked的三种方法:

.attr(‘checked’):   //看版本1.6+返回:”checked”或”undefined” ;1.5-返回:true或false
.prop(‘checked’): //16+:true/false
.is(‘:checked’):    //所有版本:true/false//别忘记冒号哦

jquery赋值checked的几种写法:

所有的jquery版本都可以这样赋值:

// $(“#cb1″).attr(“checked”,”checked”);
// $(“#cb1″).attr(“checked”,true);

jquery1.6+:prop的4种赋值:

// $(“#cb1″).prop(“checked”,true);//很简单就不说了哦
// $(“#cb1″).prop({checked:true}); //map键值对
// $(“#cb1″).prop(“checked”,function(){
return true;//函数返回true或false
});

//记得还有这种哦:$(“#cb1″).prop(“checked”,”checked”);

更多参考:http://api.jquery.com/prop/

上代码 大家可以随便测试:(你是懒人么-_-)

jquery1.6以后才支持prop的哦

新建一个text复制内容进去  后缀名改成html

<html>
    <head>
<title>测试</title>
<style type="text/css">

</style>
<!--1.62可以修改1.42 1.52 1.7来测试-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
//判断checked
       // var a=$("#cb1").attr('checked'); //看版本1.6+返回:"checked"或"undefined" ;1.5-返回:true或false
       // var b=$("#cb1").prop('checked'); //1.6+:true/false
       var c=$("#cb1").is(':checked'); //所有版本:true/false
       // alert(a);
       // alert(b);
alert(c);

//赋值 前两个所有的jquery版本都支持 prop只有jquery1.6+支持
       // $("#cb1").attr("checked","checked");//1.5-
       // $("#cb1").attr("checked",true);//1.5-
       //   $("#cb1").prop("checked","checked");//1.6+(整理的时候把这个忘记啦)
       //    $("#cb1").prop("checked",true);//1.6+
       // $("#cb1").prop({checked:true});//1.6+
      // $("#cb1").prop("checked",function(){
       // return true;//1.6+
       // });
})();

</script>
</head>
<body>
<!--赋值的时候记得去掉checked-->
<input id="cb1" type="checkbox" checked />
<input id="cb2" type="checkbox" checked="checked"/>
</body>
</html>


from : http://www.cnblogs.com/0banana0/archive/2011/11/16/2251855.html


heritrix crawler-beans.cxml

2013年8月25日 由 acefarmer 没有评论 »

 1. bean id=simpleOverrides

.springframework.beans.factory.config.PropertyOverrideConfigurer

覆盖全局

2. bean id=metadata

.archive.modules.CrawlMetadata

设置抓取信息

3. bean id=seeds

class=org.archive.modules.seeds.TextSeedModule

种子配置,可以从文件中读取种子,也可以直接设置种子

4. bean id=scope

.archive.modules.deciderules.DecideRuleSequence

URL规则控制,可以决定哪些URL要抓取,这里能够控制单站抓取

5. bean id=candidateScoper

class=org.archive.crawler.prefetch.CandidateScoper

URL范围控制,通过该范围的URL Heritrix才处理

6. bean id=preparer

.archive.crawler.prefetch.FrontierPreparer

url预处理,如设置URL的抓取深度,队列,成本控制等

 7. bean id=candidateProcessors

class=org.archive.modules.CandidateChain

处理器,引用candidateScoper去控制URL是否可以成为CrawlURI,preparer去设置深度,队列,成本控制等

8. bean id=preselector

.archive.crawler.prefetch.Preselector

预先选择器,这里会过滤掉一部分URL.如blockByRegex为拒绝正则,allowByRegex为允许正则

 9. bean id=preconditions

class=org.archive.crawler.prefetch.PreconditionEnforcer

先决条件设置,如设置IP有效期,爬虫协议文件robots.txt有效期

 10. bean id=fetchDns

class=org.archive.modules.fetcher.FetchDNS

解析DNS,获得IP

11. bean id=fetchHttp

class=org.archive.modules.fetcher.FetchHTTP

核心模块,获取URL内容,设置状态

12. bean id=extractorHttp

.archive.modules.extractor.ExtractorHTTP

核心模块,抽取URL,抽取出新的URL再次运行,如此爬虫才可以一直爬下去

  13. bean id=extractorHtml

class=org.archive.modules.extractor.ExtractorHTML

抽取HTML,包含JSP,ASP等,这里也会抽取JS,CSS等

14. bean id=extractorCss

class=org.archive.modules.extractor.ExtractorCSS

抽取CSS,无需单独配置,ExtractorHTML会调用

15. bean id=extractorJs

class=org.archive.modules.extractor.ExtractorJS

抽取JS,无需单独配置,ExtractorHTML会调用

16. warcWriter

定义采用哪种方式写文件到本地,默认是org.archive.modules.writer.WARCWriterProcesso

可以修改为org.archive.modules.writer.MirrorWriterProcessor,这样就可以抓取镜像了

Heritrix 3.1.1在windows上运行

2013年8月25日 由 acefarmer 没有评论 »

1. 下载dist: http://builds.archive.org:8080/maven2/org/archive/heritrix/heritrix/3.1.1/

2.解压到一个目录,如D盘,

3.调出你的cmd,cd到bin目录,如:D:\heritrix-3.1.1\bin

4直接敲入 heritrix -a admin:admin1234 (你登录web界面的用户名密码) 完事。前提是你jdk与环境变量啥的都设置好。

5.打开浏览器直接键入 https://localhost:8443/ ,此时会输入上面的用户名与密码

6.一会儿会多出一个cmd窗口蹦出来,不管他,有ssl错误异常啥的也不管他。

7. 在add job 处输入job名字,如test,点击create,如图

创建heritrix job

 

8. 你可以加入多个job(本文讲一个),在

Job Directories 出就回看到你的job

9 点击 job名字,会跳转到job页面,如:https://localhost:8443/engine/job/test

此时在最顶端 有 configuration: .\jobs\test\crawler-beans.cxml [edit] 字样

 

点击Edit配置你的job

a) metadata.operatorContactUrl=ENTER_AN_URL_WITH_YOUR_CONTACT_INFO_HERE_FOR_WEBMASTERS_AFFECTED_BY_YOUR_CRAWL

此处输入你控制爬出的地址,一般是本地,那就http://127.0.0.1

metadata.jobName=basic,job 名字,如test

metadata.description=Basic crawl starting with useful defaults,这个是job的描述,随便你改不改,

 

b)配置种子,

# URLS HERE

http://example.example/example 表示抓取的地址.比如

http://news.baidu.com

 

c) 配置模拟浏览器,查找 userAgentTemplate(原本被注解掉,打开)

<property name=”userAgentTemplate”  value=”Mozilla/5.0 (compatible; heritrix/@VERSION@ +@OPERATOR_CONTACT_URL@)”/>

 

将 @VERSION@修改为你heritrix版本,这里是3.1.1,@OPERATOR_CONTACT_URL@保持不变(不然会报错,也许是bug,3.1.1,3.1.2都有这问题)

修改后的情况应该是:

<property name=”userAgentTemplate”  value=”Mozilla/5.0 (compatible; heritrix/3.1.2 +@OPERATOR_CONTACT_URL@)”/>

而其他几个直接注释掉

<!– <property name=”operatorContactUrl” value=”[see override above]“/>
<property name=”jobName” value=”[see override above]“/>
<property name=”description” value=”[see override above]“/>–>

将operaterFrom 打开,填入你的email,模拟浏览器,跟以前1.X的设置差不多,以前是分开的,以防被拦截。

<property name=”operatorFrom” value=”acefarmer@163.com”/>

点击save changes,然后回到 https://localhost:8443/engine

点击进入你想抓取的job,并点击launch 开始抓取

如果状态不为running,点击unpause,

开始运行后你会在你job文件夹下生成你job名字,然后又个以时间结尾的文件夹,

G:\heritrix-3.1.2-SNAPSHOT\bin\jobs\guos\20130825022631

该文件夹下有个warcs文件夹就是你抓取的内容,日后如果采用mirrorWriter的话就会是一个个网页了

本文只是基本全网抓取,后面讲限定网站,镜像抓取等。

 

office 2007,2010无法打开doc,提示文件已损坏的解决办法

2013年8月13日 由 acefarmer 没有评论 »

如果在Word 2010中打开从网络上下载的文档doc,docx,将默认是处于受保护状态。当你双击打开时,会提示文件已经损坏无法打开。

 

临时解决办法:修改文件属性
选择需要打开的文件,点右键属性里面选择”解除锁定”,然后确定后。即可正常打开了。

 
彻底解决办法:修改选项配置
进入文件菜单中的选项->信任中心->点信任中心设置 然后点受保护的视图,把右边的所有钩上的内容都不钩,最后保存退出即可

没Android手机,电脑一样当手机玩

2013年8月10日 由 acefarmer 没有评论 »

只需要下载一个Android模拟器(bluestacks),然后任何apk都可以在pc上玩了,再也不觉得屏幕小啦,想耍啥游戏就耍啥。再牛逼的手机,应该没你的pc拽吧!

http://www.bluestacks.net.cn/

访问google.com而不是.hk的最有效方法

2013年8月10日 由 acefarmer 没有评论 »

这个很简单,

直接访问: http://www.google.com/ncr

就不再是google.com.hk啦,你想怎么玩就怎么玩

WordPress缓存超级组合Hyper Cache+DB Cache Reloaded Fix

2013年8月4日 由 acefarmer 没有评论 »

要想你的小站飞快,页面缓存与数据库缓存那是必不可少的,

强烈推荐使用Hyper Cache

http://wordpress.org/extend/plugins/hyper-cache/

 

与 DB Cache Reloaded Fix

http://wordpress.org/plugins/db-cache-reloaded-fix/

 

这个真的不错,关键是小而精悍

 

重庆卤菜配方

2013年7月14日 由 acefarmer 没有评论 »

卤菜,是将初步加工和焯水处理后的原料放在配好的卤汁中煮制而成的菜肴。现将制作技术介绍如下:

一、卤汁的配制   卤汁的配制,是做好卤菜的首要关键。卤汁配制的好坏,将直接影响到卤菜的色泽和口味质量6卤汁一般可分为红卤汁、黄卤汁、白卤汁三大类。

1.红卤汁。八角20克,桂皮20克,陈皮50克,丁香8克,山奈20克,花椒20克,茴香15克,香叶20克,良姜20克,草果5个,甘草15克,干红辣椒100克,香葱150克,生姜150克,片糖250克,黄酒1000克,优质酱油500克,糖色50克,精盐200克,热花生油250克,味精100克,骨汤12千克。

制法:①草果用刀拍裂,桂皮用刀背敲成小块,甘草切成厚片,香葱挽结,生姜用刀拍松,红辣椒干切成段。②将八角、桂皮、陈皮、丁香、山奈、花椒、茴香、香叶、草果,良姜、甘草、红辣椒干一起装入香料袋内,袋口扎牢。③将香料袋、葱结、姜块、片糖、黄酒、酱油、糖色、精盐、熟花生油、味精、骨汤一起放入卤锅内,调匀即可。

2.黄卤汁。黄栀子150克,香叶100克,山奈50克,花椒25克,良姜50克,砂仁25克,油炸蒜仁150克,油炸鲜桔皮150克,芹菜150克,生姜150克,沙嗲酱1瓶,黄酒1000克,熟菜籽油250克,油咖喱150克,味精200克,精盐230克,骨汤12千克。

制法:①黄栀子用刀拍裂,芹菜打成结,生姜用刀拍松。②将黄栀子、香叶、山奈、花椒、良姜、砂仁、油炸蒜仁、油炸鲜桔皮装入香料袋内,袋口扎牢。③将香料袋、芹菜结、生姜块、沙嗲酱、黄酒、热菜籽油、油咖喱、精盐、骨汤一起入放卤锅内,调匀即可。

3.白卤汁。八角60克,山奈50克,花椒25克,白豆蔻25克、陈皮50克,香叶50克,白芷25克,香葱150克,生姜150克,水酒1000克,白酱油1000克,精盐120克,味精100克,骨汤12千克。

制法:①香葱挽结,生姜用刀拍松。将八角、山奈、花椒、白豆蔻、陈皮、香叶、白芷装入香料袋内,袋口扎牢。②将香料袋、葱结、姜块、水酒、白酱油、精盐、味精、骨汤一起放入卤锅内,调匀即可。   以上配方适宜于卤制10~12千克的生鲜原料(家庭可根据原料的数量,按比例减少调味料的数量)。

4.配制卤汁时应注意的事项。

①香料、食盐、酱油的用量要适当:香料过多,成菜药味大,色泽偏黑;香料太少,成菜香味不足。食盐过多,成菜除口味“死咸”外,还会使成菜紧缩、干瘪;食盐太少,成菜鲜香味不突出。酱油太多,成品色黑难看;酱油太少,口味不够鲜美。

②原料的选用:黄卤汁、白卤汁不宜使用酱油或别的带色的调味品,也不要使用容易褪色的香料。

③卤汁不宜事先熬煮,应现配制现使用,这样既可避免调味品中的芳香气味白白地挥发掉,还能节省燃料和时间。

 

卤汁的保管

卤过菜肴的卤汁,应注意保存,留作下次用。卤汁用的次数越多,保存时间越长,质量越佳,味道越美。这是因为卤汁内所含的可溶性蛋白质等成分越来越多的缘故。

卤汁的保存,应注意以下几点:

1.撇除浮油、浮沫。卤汁的浮油、浮沫要经常撇除,并经常过滤去渣。

2.要定时加热消毒。夏秋季每天早晚各烧沸消毒1次,春冬季可每日或隔日烧沸消毒1次,烧沸后的卤汁应放消过毒的盛器内。

3.盛器必须用陶器或白搪瓷器皿。绝不能用铁、锡、铝、铜等金属器皿,否则卤汁中的盐等物质会与金属发生化学反应,使卤汁变色变味,乃至变质不能使用。

4.注意存放位置。卤汁应放在阴凉、通风、防尘处,加上纱罩,防止蝇虫等落入卤汁中。

5.原料的添加。香料袋一般只用2次,就应更换。其它调味料则应每卤一次原料,即添加一次。

附注:有了老卤后,调制卤汁则不必非用骨汤,用清水亦可,也可不加油了。

Eclipse.ini配置

2013年7月7日 由 acefarmer 没有评论 »

Eclipse的启动由$ECLIPSE_HOME/eclipse.ini控制,如果$ECLIPSE_HOME 没有被定义,则Eclipse安装目录下的默认eclipse.ini会生效。

eclipse.ini是一个文本文件,其内容相当于在Eclipse运行时添加到 Eclipse.exe之后的命令行参数。

其格式要求:

1:所有的选项及其相关的参数必须在单独的一行之内

2:所有在-vmargs之后的参数将会被传输给JVM,所有如果所有对Eclipse 设置的参数必须写在-vmargs之前(就如同你在命令行上使用这些参数一样)
默认情况下,eclipse.ini的内容如下:

-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
-vmargs
-Xms40m
-Xmx256m

上面的配置表示堆空间初始大小为40M,最大为256M,PermGen最大为256M。

指定虚拟机

建议你使用eclipse.ini来指定一个确定的JVM,而不是使用默认的情况,因为很多情况下你无法确认你的Eclipse到底使用的你机器上安装的哪个JVM,使用eclipse.ini来指定使得你能指定并确认之。

下面的例子将展示如何正确的使用 -vm选项

注意-vm选项的格式有严格的要求:
1:-vm选项和它的值(路径)必须在单独的一行
2:其值必须严格地指向Java可执行文件,而不仅仅只是Java home目录。
3:-vm选项必须在-vmargs选项之前,之前已经说过,所有在-vmargs之后的选项将会直接被传递给JVM

Windows Example

-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
-vm
C:\Java\JDK\1.5\bin\javaw.exe
-vmargs
-Xms40m
-Xmx512m

Linux Example

在Linux操作系统中,格式和Windows中很类似

-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
-vm
/opt/sun-jdk-1.6.0.02/bin/java
-vmargs
-Xms40m
-Xmx512m

Mac OS X Example

指定Java 6:

-showsplash
org.eclipse.platform
–launcher.XXMaxPermSize
256m
-vm
/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/bin/java
-vmargs
-Xms40m
-Xmx512m

堆(Heap)和非堆(Non-heap)内存
按照官方的说法:“Java虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java
虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。
简单来说堆就是Java代码可及的内存,是留给开发人员使用的;
非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法
的代码都在非堆内存中。
堆内存分配:
JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;
JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。
因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。

非堆内存分配:
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

JVM内存限制(最大值)
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。
简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说
Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。

设置VM参数导致程序无法启动主要有以下几种原因:
1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;
2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。
说到实际物理内存这里需要说明一点的是,如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。

为何将上面的参数写入到eclipse.ini文件Eclipse没有执行对应的设置?
那为什么同样的参数在快捷方式或者命令行中有效而在eclipse.ini文件中是无效的呢?这是因为我们没有遵守eclipse.ini文件的设置规则:
参数形如“项 值”这种形式,中间有空格的需要换行书写,如果值中有空格的需要用双引号包括起来。比如我们使用-vm
C:\Java\jre1.6.0\bin\javaw.exe参数设置虚拟机,在eclipse.ini文件中要写成这样:
-vm
C:\Java\jre1.6.0\bin\javaw.exe

按照上面所说的,最后参数在eclipse.ini中可以写成这个样子:
-vmargs
-Xms128M
-Xmx512M

-XX:PermSize=64M
-XX:MaxPermSize=128M
实际运行的结果可以通过Eclipse中
“Help”-“About Eclipse SDK”窗口里面的“Configuration Details”按钮进行查看。
另外需要说明
的是,Eclipse压缩包中自带的eclipse.ini文件内容是这样的:
-showsplash
org.eclipse.platform

–launcher.XXMaxPermSize
256m
-vmargs
-Xms40m
-Xmx256m

其中–launcher.XXMaxPermSize(注意最前面是两个连接线)跟-XX:MaxPermSize参数的含义基本是一样的,我
觉得唯一的区别就是前者是eclipse.exe启动的时候设置的参数,而后者是eclipse所使用的JVM中的参数。其实二者设置一个就可以了,所以
这里可以把 –launcher.XXMaxPermSize和下一行使用#注释掉。

其他的启动参数。 如果你有一个双核的CPU,也许可以尝试这个参数:
-XX:+UseParallelGC
让GC可以更快的执行。

文章出处:

http://www.cnblogs.com/yan5lang/archive/2011/05/24/2055867.html

 

freemarker判空与设置默认值

2013年6月29日 由 acefarmer 没有评论 »

Welcome ${user!}!

Welcome ${user!’your name’}!

 

或者 ${user?if_exists}

${user?default(‘your name’)}

如果user为空,则上面会输出

Welcome !

Welcome your name!

这样就可以避免freemarker报错