JVM的内存区域划分

没有评论

2016 年 09 月 26 日 at 下午 8:26分类:java

学过C语言的朋友都知道C编译器在划分内存区域的时候经常将管理的区域划分为数据段和代码段,数据段包括堆、栈以及静态数据区。那么在Java语言当中,内存又是如何划分的呢?

由于Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分。在讨论JVM内存区域划分之前,先来看一下Java程序具体执行的过程:

如上图所示,首先Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。在整个程序执行过程中,JVM会用一段空间来存储程序执行期间需要用到的数据和相关信息,这段空间一般被称作为Runtime Data Area(运行时数据区),也就是我们常说的JVM内存。因此,在Java中我们常常说到的内存管理就是针对这段空间进行管理(如何分配和回收内存空间)。

在知道了JVM内存是什么东西之后,下面我们就来讨论一下这段空间具体是如何划分区域的,是不是也像C语言中一样也存在栈和堆呢?

一.运行时数据区包括哪几部分?

根据《Java虚拟机规范》的规定,运行时数据区通常包括这几个部分:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。

如上图所示,JVM中的运行时数据区应该包括这些部分。在JVM规范中虽然规定了程序在执行期间运行时数据区应该包括这几部分,但是至于具体如何实现并没有做出规定,不同的虚拟机厂商可以有不同的实现方式。

二.运行时数据区的每部分到底存储了哪些数据?

下面我们来了解一下运行时数据区的每部分具体用来存储程序执行过程中的哪些数据。

1.程序计数器

程序计数器(Program Counter Register),也有称作为PC寄存器。想必学过汇编语言的朋友对程序计数器这个概念并不陌生,在汇编语言中,程序计数器是指CPU中的寄存器,它保存的是程序当前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址),当CPU需要执行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址,然后根据得到的地址获取到指令,在得到指令之后,程序计数器便自动加1或者根据转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令。

虽然JVM中的程序计数器并不像汇编语言中的程序计数器一样是物理概念上的CPU寄存器,但是JVM中的程序计数器的功能跟汇编语言中的程序计数器的功能在逻辑上是等同的,也就是说是用来指示 执行哪条指令的。

由于在JVM中,多线程是通过线程轮流切换来获得CPU执行时间的,因此,在任一具体时刻,一个CPU的内核只会执行一条线程中的指令,因此,为了能够使得每个线程都在线程切换后能够恢复在切换之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰,否则就会影响到程序的正常执行次序。因此,可以这么说,程序计数器是每个线程所私有的。

在JVM规范中规定,如果线程执行的是非native方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是native方法,则程序计数器中的值是undefined。

由于程序计数器中存储的数据所占空间的大小不会随程序的执行而发生改变,因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。

2.Java栈

Java栈也称作虚拟机栈(Java Vitual Machine Stack),也就是我们常常所说的栈,跟C语言的数据段中的栈类似。事实上,Java栈是Java方法执行的内存模型。为什么这么说呢?下面就来解释一下其中的原因。

Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。当线程执行一个方法时,就会随之创建一个对应的栈帧,并将建立的栈帧压栈。当方法执行完毕之后,便会将栈帧出栈。因此可知,线程当前执行的方法所对应的栈帧必定位于Java栈的顶部。讲到这里,大家就应该会明白为什么 在 使用 递归方法的时候容易导致栈内存溢出的现象了以及为什么栈区的空间不用程序员去管理了(当然在Java中,程序员基本不用关系到内存分配和释放的事情,因为Java有自己的垃圾回收机制),这部分空间的分配和释放都是由系统自动实施的。对于所有的程序设计语言来说,栈这部分空间对程序员来说是不透明的。下图表示了一个Java栈的模型:

局部变量表,顾名思义,想必不用解释大家应该明白它的作用了吧。就是用来存储方法中的局部变量(包括在方法中声明的非静态变量以及函数形参)。对于基本数据类型的变量,则直接存储它的值,对于引用类型的变量,则存的是指向对象的引用。局部变量表的大小在编译器就可以确定其大小了,因此在程序执行期间局部变量表的大小是不会改变的。

操作数栈,想必学过数据结构中的栈的朋友想必对表达式求值问题不会陌生,栈最典型的一个应用就是用来对表达式求值。想想一个线程执行方法的过程中,实际上就是不断执行语句的过程,而归根到底就是进行计算的过程。因此可以这么说,程序中的所有计算过程都是在借助于操作数栈来完成的。

指向运行时常量池的引用,因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向运行时常量。

方法返回地址,当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。

由于每个线程正在执行的方法可能不同,因此每个线程都会有一个自己的Java栈,互不干扰。

3.本地方法栈

本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。在JVM规范中,并没有对本地方发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接就把本地方法栈和Java栈合二为一。

4.堆

在C语言中,堆这部分空间是唯一一个程序员可以管理的内存区域。程序员可以通过malloc函数和free函数在堆上申请和释放空间。那么在Java中是怎么样的呢?

Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)。只不过和C语言中的不同,在Java中,程序员基本不用去关心空间释放的问题,Java的垃圾回收机制会自动进行处理。因此这部分空间也是Java垃圾收集器管理的主要区域。另外,堆是被所有线程共享的,在JVM中只有一个堆。

5.方法区

方法区在JVM中也是一个非常重要的区域,它与堆一样,是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。

在Class文件中除了类的字段、方法、接口等描述信息外,还有一项信息是常量池,用来存储编译期间生成的字面量和符号引用。

在方法区中有一个非常重要的部分就是运行时常量池,它是每一个类或接口的常量池的运行时表示形式,在类和接口被加载到JVM后,对应的运行时常量池就被创建出来。当然并非Class文件常量池中的内容才能进入运行时常量池,在运行期间也可将新的常量放入运行时常量池中,比如String的intern方法。

在JVM规范中,没有强制要求方法区必须实现垃圾回收。很多人习惯将方法区称为“永久代”,是因为HotSpot虚拟机以永久代来实现方法区,从而JVM的垃圾收集器可以像管理堆区一样管理这部分区域,从而不需要专门为这部分设计垃圾回收机制。不过自从JDK7之后,Hotspot虚拟机便将运行时常量池从永久代移除了。

以上为个人看法和观点,如有不正之处希望谅解并欢迎指正。

  参考资料:

http://blog.csdn.net/ns_code/article/details/17565503

http://www.cnblogs.com/sunada2005/p/3577799.html

《深入理解Java虚拟机》

《Java虚拟机规范 SE7》

线程池

没有评论

2016 年 08 月 23 日 at 下午 9:11分类:java

线程池的优点:

  • 重用线程池中的线程,避免频繁创建和销毁带来的性能开销
  • 可以有效控制线程池中的最大并发数,避免大量线程之间互相抢占系统资源导致阻塞
  • 可以对线程进行简单管理。

线程运行机制

  • 开启线程过多,会消耗cpu资源
  • 单核cpu,同一时刻只能处理一个线程,多核cpu同一时刻可以处理多个线程
  • 操作系统为每个运行线程安排一定的CPU时间—-时间片,系统通过一种循环的方式为线程提供时间片,线程在自己的时间内运行,因为时间相当短,多个线程频繁地发生切换,因此给用户的感觉就是好像多个线程同时运行一样,但是如果计算机有多个CPU,线程就能真正意义上的同时运行了.

线程池的作用

  • 线程池是预先创建线程的一种技术。线程池在还没有任务到来之前,创建一定数量的线程,放入空闲队列中,然后对这些资源进行复用。减少频繁的创建和销毁对象。
  • 频繁创建和销毁线程耗资源,耗时间
  • 因为有的线程执行时间比创建和销毁一个线程的时间还短

解读EXPLAIN执行计划中的key_len

没有评论

2016 年 02 月 08 日 at 下午 8:46分类:Mysql

EXPLAIN中的key_len一列表示什么意思,该如何解读?

EXPLAIN执行计划中有一列 key_len 用于表示本次查询中,所选择的索引长度有多少字节,通常我们可借此判断联合索引有多少列被选择了。

在这里 key_len 大小的计算规则是:

  • 一般地,key_len 等于索引列类型字节长度,例如int类型为4-bytes,bigint为8-bytes;
  • 如果是字符串类型,还需要同时考虑字符集因素,例如:CHAR(30) UTF8则key_len至少是90-bytes;
  • 若该列类型定义时允许NULL,其key_len还需要再加 1-bytes;
  • 若该列类型为变长类型,例如 VARCHAR(TEXT\BLOB不允许整列创建索引,如果创建部分索引,也被视为动态列类型),其key_len还需要再加 2-bytes;

综上,看下面几个例子:

列类型 key_len 备注
id int key_len = 4+1 = 5 允许NULL,加1-byte
id int not null key_len = 4 不允许NULL
user char(30) utf8 key_len = 30*3+1 允许NULL
user varchar(30) not null utf8 key_len = 30*3+2 动态列类型,加2-bytes
user varchar(30) utf8 key_len = 30*3+2+1 动态列类型,加2-bytes;允许NULL,再加1-byte
detail text(10) utf8 key_len = 30*3+2+1 TEXT列截取部分,被视为动态列类型,加2-bytes;且允许NULL

备注,key_len 只指示了WHERE中用于条件过滤时被选中的索引列,是不包含 ORDER BY/GROUP BY 这部分被选中的索引列。

例如,有个联合索引 idx1(c1, c2, c3),3个列均是INT NOT NULL,那么下面的这个SQL执行计划中,key_len的值是8而不是12:

SELECT…WHERE c1=? AND c2=? ORDER BY c1;

Java中的堆和栈的区别

没有评论

2016 年 02 月 08 日 at 下午 8:05分类:java

当一个人开始学习Java或者其他编程语言的时候,会接触到堆和栈,由于一开始没有明确清晰的说明解释,很多人会产生很多疑问,什么是堆,什么是栈,堆和栈有什么区别?更糟糕的是,Java中存在栈这样一个后进先出(Last In First Out)的顺序的数据结构,这就是java.util.Stack。这种情况下,不免让很多人更加费解前面的问题。事实上,堆和栈都是内存中的一部分,有着不同的作用,而且一个程序需要在这片区域上分配内存。众所周知,所有的Java程序都运行在JVM虚拟机内部,我们这里介绍的自然是JVM(虚拟)内存中的堆和栈。

区别

java中堆和栈的区别自然是面试中的常见问题,下面几点就是其具体的区别

各司其职

最主要的区别就是栈内存用来存储局部变量和方法调用。
而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。

独有还是共享

栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。

异常错误

如果栈内存没有可用的空间存储方法调用和局部变量,JVM会抛出java.lang.StackOverFlowError。
而如果是堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError。

空间大小

栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没有及时跳出,很可能发生StackOverFlowError问题。
你可以通过-Xss选项设置栈内存的大小。-Xms选项可以设置堆的开始时的大小,-Xmx选项可以设置堆的最大值。

这就是Java中堆和栈的区别。理解好这个问题的话,可以对你解决开发中的问题,分析堆内存和栈内存使用,甚至性能调优都有帮助。

如何查看linux版本 如何查看LINUX是多少位

没有评论

2015 年 11 月 30 日 at 下午 8:07分类:Linux

一、如何得知自己正在使用的linux是什么版本呢,下面的几种方法将给你带来答案!

1. 查看内核版本命令:

1) [root@q1test01 ~]# cat /proc/version

Linux version 2.6.9-22.ELsmp (bhcompile@crowe.devel.redhat.com) (gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)) #1 SMP Mon Sep 19 18:00:54 EDT 2005

2) [root@q1test01 ~]# uname -a

Linux q1test01 2.6.9-22.ELsmp #1 SMP Mon Sep 19 18:00:54 EDT 2005 x86_64 x86_64 x86_64 GNU/Linux

3) [root@q1test01 ~]# uname -r

2.6.9-22.ELsmp

2. 查看linux版本:

1) 登录到服务器执行 lsb_release -a ,即可列出所有版本信息,例如:

[root@3.5.5Biz-46 ~]# [root@q1test01 ~]# lsb_release -a

LSB Version: :core-3.0-amd64:core-3.0-ia32:core-3.0-noarch:graphics-3.0-amd64:graphics-3.0-

ia32:graphics-3.0-noarch

Distributor ID: RedHatEnterpriseAS

Description: Red Hat Enterprise Linux AS release 4 (Nahant Update 2)

Release: 4

Codename: NahantUpdate2

注:这个命令适用于所有的linux,包括Redhat、SuSE、Debian等发行版。

2) 登录到linux执行cat /etc/issue,例如如下:

[root@q1test01 ~]# cat /etc/issue

Red Hat Enterprise Linux AS release 4 (Nahant Update 2)

Kernel \r on an \m

3) 登录到linux执行cat /etc/redhat-release ,例如如下:

[root@q1test01 ~]# cat /etc/redhat-release

Red Hat Enterprise Linux AS release 4 (Nahant Update 2)

注:这种方式下可以直接看到具体的版本号,比如 AS4 Update 1

4)登录到linux执行rpm -q redhat-release ,例如如下:

[root@q1test01 ~]# rpm -q redhat-release

redhat-release-4AS-3

注:这种方式下可看到一个所谓的release号,比如上边的例子是3

这个release号和实际的版本之间存在一定的对应关系,如下:

redhat-release-3AS-1 -> Redhat Enterprise Linux AS 3

redhat-release-3AS-7.4 -> Redhat Enterprise Linux AS 3 Update 4

redhat-release-4AS-2 -> Redhat Enterprise Linux AS 4

redhat-release-4AS-2.4 -> Redhat Enterprise Linux AS 4 Update 1

redhat-release-4AS-3 -> Redhat Enterprise Linux AS 4 Update 2

redhat-release-4AS-4.1 -> Redhat Enterprise Linux AS 4 Update 3

redhat-release-4AS-5.5 -> Redhat Enterprise Linux AS 4 Update 4

另:第3)、4)两种方法只对Redhat Linux有效。

二、如何查看LINUX是多少位

1. 查看linux机器是32位还是64位的方法:

file /sbin/init 或者file /bin/ls
/sbin/init: ELF64-bitLSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

如果显示 64-bit 则为64位;

file /sbin/init
/sbin/init: ELF32-bitLSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

如果显示为32 bit 则为32bit;

uname -a:
uname -a
Linux pmx002**.**.** 2.6.32-71.el6.x86_64 #1 SMP Wed Sep 1 01:33:01 EDT 2010x86_64x86_64 x86_64 GNU/Linux

x86_64表示64位机器

uname -a
Linux pmx0**.**.** 2.6.9-5.ELsmp #1 SMP Wed Jan 5 19:30:39 EST 2005i686i686 i386 GNU/Linux

i686表示32位机器

i686 只是i386的一个子集,支持的cpu从Pentium 2 (686)开始,之前的型号不支持.

备注:

1. i386 适用于intel和AMD所有32位的cpu.以及via采用X86架构的32的cpu.

intel平台包括8086,80286,80386,80486,奔腾系列(1.2.3.4)、赛扬系列,Pentium D系列

以及centrino P-M,core duo 等.

2. X86_64 适用于intel的Core 2 Duo, Centrino Core 2 Duo, and Xeon 和AMD Athlon64/x2, Sempron64/x2, Duron64等采用X86架构的64位cpu.

3. PPC 适用于Apple Macintosh G3, G4, G5, PowerBook, and other non-Intel models

安装DVD包括的软件要比安装光盘多一些,安装DVD也包括了两种图形界面(KDE和gnome).

4.Jigdo

也可以通过 Jigdo 下载 Fedora 发行版。Jigdo 可以加速下载安装盘的 ISO 镜像。同 BT 下载等待任务完全完成所不同,Jidgo 自动定位最快的镜像服务器(通过 Fedora 镜像管理器),并且从中下载所需要的文件。为了减少所需的网络流量,可以让 Jigdo 扫描现存的 DVD 或 CD 介质。这个功能对于以下用户特别有用。

2. getconf LONG_BIT
在32位和64位机器上运行如下命令,结果如下:
[b@002 ~]$ getconf LONG_BIT
64

[root@pmx4 /]# getconf LONG_BIT
32

遍历Map的四种方法

没有评论

2015 年 11 月 06 日 at 下午 6:05分类:java

public static void main(String[] args) {

  Map<String, String> map = new HashMap<String, String>();
  map.put("1", "value1");
  map.put("2", "value2");
  map.put("3", "value3");

  //第一种:普遍使用,二次取值
  System.out.println("通过Map.keySet遍历key和value:");
  for (String key : map.keySet()) {
   System.out.println("key= "+ key + " and value= " + map.get(key));
  }

  //第二种
  System.out.println("通过Map.entrySet使用iterator遍历key和value:");
  Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
  while (it.hasNext()) {
   Map.Entry<String, String> entry = it.next();
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
  }

  //第三种:推荐,尤其是容量大时
  System.out.println("通过Map.entrySet遍历key和value");
  for (Map.Entry<String, String> entry : map.entrySet()) {
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
  }

  //第四种
  System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
  for (String v : map.values()) {
   System.out.println("value= " + v);
  }
 }

IntelliJ IDEA 使用总结

没有评论

2015 年 10 月 30 日 at 下午 6:15分类:java

实用快捷键:

Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*…*/ )
Ctrl+D 复制行
Ctrl+X 删除行
快速修复 alt+enter (modify/cast)
代码提示 alt+/
ctr+G 定位某一行
Shift+F6 重构-重命名
Ctrl+R 替换文本
Ctrl+F 查找文本
Ctrl+E 最近打开的文件
Ctrl+J 自动代码

组织导入 ctr+alt+O
格式化代码 ctr+alt+L
大小写转化 ctr+shift+U

————————–

IntelliJ Idea 常用快捷键列表
Alt+回车 导入包,自动修正
Ctrl+N   查找类
Ctrl+Shift+N 查找文件
Ctrl+Alt+L  格式化代码
Ctrl+Alt+O 优化导入的类和包
Alt+Insert 生成代码(如get,set方法,构造函数等)
Ctrl+E或者Alt+Shift+C  最近更改的代码
Ctrl+R 替换文本
Ctrl+F 查找文本
Ctrl+Shift+Space 自动补全代码
Ctrl+空格 代码提示
Ctrl+Alt+Space 类名或接口名提示
Ctrl+P 方法参数提示
Ctrl+Shift+Alt+N 查找类中的方法或变量
Alt+Shift+C 对比最近修改的代码
Shift+F6  重构-重命名
Ctrl+Shift+先上键
Ctrl+X 删除行
Ctrl+D 复制行
Ctrl+/ 或 Ctrl+Shift+/  注释(// 或者/*…*/ )
Ctrl+J  自动代码
Ctrl+E 最近打开的文件
Ctrl+H 显示类结构图
Ctrl+Q 显示注释文档
Alt+F1 查找代码所在位置
Alt+1 快速打开或隐藏工程面板
Ctrl+Alt+ left/right 返回至上次浏览的位置
Alt+ left/right 切换代码视图
Alt+ Up/Down 在方法间快速移动定位

Ctrl+Shift+Up/Down 代码向上/下移动。

F2 或Shift+F2 高亮错误或警告快速定位
代码标签输入完成后,按Tab,生成代码。
选中文本,按Ctrl+Shift+F7 ,高亮显示所有该文本,按Esc高亮消失。
Ctrl+W 选中代码,连续按会有其他效果
选中文本,按Alt+F3 ,逐个往下查找相同文本,并高亮显示。
Ctrl+Up/Down 光标跳转到第一行或最后一行下
Ctrl+B 快速打开光标处的类或方法
————————————————————————————————————

1. IDEA内存优化

因机器本身的配置而配置:

\IntelliJ IDEA 8\bin\idea.exe.vmoptions
—————————————–
-Xms64m
-Xmx256m
-XX:MaxPermSize=92m
-ea
-server
-Dsun.awt.keepWorkingSetOnMinimize=true

2. 查询快捷键

CTRL+N   查找类
CTRL+SHIFT+N  查找文件
CTRL+SHIFT+ALT+N 查找类中的方法或变量
CIRL+B   找变量的来源
CTRL+ALT+B  找所有的子类
CTRL+SHIFT+B  找变量的类
CTRL+G   定位行
CTRL+F   在当前窗口查找文本
CTRL+SHIFT+F  在指定窗口查找文本
CTRL+R   在 当前窗口替换文本
CTRL+SHIFT+R  在指定窗口替换文本
ALT+SHIFT+C  查找修改的文件
CTRL+E   最近打开的文件
F3   向下查找关键字出现位置
SHIFT+F3  向上一个关键字出现位置
F4   查找变量来源
CTRL+ALT+F7  选中的字符查找工程出现的地方
CTRL+SHIFT+O  弹出显示查找内容

3. 自动代码

ALT+回车  导入包,自动修正
CTRL+ALT+L  格式化代码
CTRL+ALT+I  自动缩进
CTRL+ALT+O  优化导入的类和包
ALT+INSERT  生成代码(如GET,SET方法,构造函数等)
CTRL+E 最近更改的代码
CTRL+SHIFT+SPACE 自动补全代码
CTRL+空格  代码提示
CTRL+ALT+SPACE  类名或接口名提示
CTRL+P   方法参数提示
CTRL+J   自动代码
CTRL+ALT+T  把选中的代码放在 TRY{} IF{} ELSE{} 里

4. 复制快捷方式

CTRL+D   复制行
CTRL+X   剪切,删除行

5. 其他快捷方式

CIRL+U   大小写切换
CTRL+Z   倒退
CTRL+SHIFT+Z  向前
CTRL+ALT+F12  资源管理器打开文件夹
ALT+F1   查找文件所在目录位置
SHIFT+ALT+INSERT 竖编辑模式
CTRL+/   注释//
CTRL+SHIFT+/  注释/*…*/
CTRL+W   选中代码,连续按会有其他效果
CTRL+B   快速打开光标处的类或方法
ALT+ ←/→  切换代码视图
CTRL+ALT ←/→  返回上次编辑的位置
ALT+ ↑/↓  在方法间快速移动定位
SHIFT+F6  重构-重命名
CTRL+H   显示类结构图
CTRL+Q   显示注释文档
ALT+1   快速打开或隐藏工程面板
CTRL+SHIFT+UP/DOWN 代码向上/下移动。
CTRL+UP/DOWN  光标跳转到第一行或最后一行下
ESC   光标返回编辑框
SHIFT+ESC  光标返回编辑框,关闭无用的窗口
F1   帮助千万别按,很卡!
CTRL+F4   非常重要下班都用

 

http://www.cnblogs.com/bluestorm/archive/2013/05/20/3087889.html

git 分支 合并

没有评论

2015 年 10 月 24 日 at 下午 12:28分类:web

1、创建分支
创建分支很简单:git branch <分支名>
2、切换分支
git checkout <分支名>
该语句和上一个语句可以和起来用一个语句表示:git checkout -b <分支名>
3、分支合并
比如,如果要将开发中的分支(develop),合并到稳定分支(master),
首先切换的master分支:git checkout master。
然后执行合并操作:git merge develop。
如果有冲突,会提示你,调用git status查看冲突文件。
解决冲突,然后调用git add或git rm将解决后的文件暂存。
所有冲突解决后,git commit 提交更改。
4、分支衍合
分支衍合和分支合并的差别在于,分支衍合不会保留合并的日志,不留痕迹,而 分支合并则会保留合并的日志。
要将开发中的分支(develop),衍合到稳定分支(master)。
首先切换的master分支:git checkout master。
然后执行衍和操作:git rebase develop。
如果有冲突,会提示你,调用git status查看冲突文件。
解决冲突,然后调用git add或git rm将解决后的文件暂存。
所有冲突解决后,git rebase –continue 提交更改。
5、删除分支
执行git branch -d <分支名>
如果该分支没有合并到主分支会报错,可以用以下命令强制删除git branch -D <分支名>

Spring @Autowired,@Resource,@Required注解的用法和作用

没有评论

2015 年 10 月 22 日 at 下午 8:55分类:Php

@Autowired的用法和作用

这个注解就是spring可以自动帮你把bean里面引用的对象的setter/getter方法省略,它会自动帮你set/get。

<bean id=”userDao”class=”…”/>

<bean id=”userService”class=”…”>

<property name=”userDao”>

<ref bean=”userDao”/>

</property>

</bean>

这样你在userService里面要做一个userDao的setter/getter方法。

但如果你用了@Autowired的话,你只需要在UserService的实现类中声明即可。

@Autowired

private IUserDao userdao;

Spring@Autowired注解与自动装配

1   配置文件的方法

我们编写spring 框架的代码时候。一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量。并且要配套写上 get 和 set方法。

Boss 拥有 Office 和 Car 类型的两个属性:

3. Boss.java

public class Boss {

private Car car;

private Office office;

// 省略 get/setter

@Override

public String toString() {

return “car:” + car + “/n” + “office:” +office;

}

}

我们在 Spring 容器中将 Office 和 Car 声明为 Bean,并注入到 Boss Bean 中:下面是使用传统 XML 完成这个工作的配置文件 beans.xml:

beans.xml 将以上三个类配置成 Bean

<?xml version=”1.0″encoding=”UTF-8″ ?>

<beansxmlns=”http://www.springframework.org/schema/beans”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd”>

<bean id=”boss”>

<property name=”car” ref=”car”/>

<property name=”office” ref=”office” />

</bean>

<bean id=”office”>

<property name=”officeNo” value=”002″/>

</bean>

<bean id=”car”scope=”singleton”>

<property name=”brand”value=” 红旗 CA72″/>

<property name=”price” value=”2000″/>

</bean>

</beans>

当我们运行以下代码时,控制台将正确打出 boss 的信息:

清单 5. 测试类:AnnoIoCTest.java

import org.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

public class AnnoIoCTest {

public static void main(String[] args) {

String[] locations = {“beans.xml”};

ApplicationContext ctx =

new ClassPathXmlApplicationContext(locations);

Boss boss = (Boss) ctx.getBean(“boss”);

System.out.println(boss);

}

}

这说明 Spring 容器已经正确完成了 Bean 创建和装配的工作。

2. @Autowired

Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。通过 @Autowired的使用来消除 set ,get方法。

要实现我们要精简程序的目的。需要这样来处理:

在applicationContext.xml中加入:

<!– 该 BeanPostProcessor 将自动对标注@Autowired 的 Bean 进行注入 –>

<beanclass=”org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor”/>

Spring 通过一个BeanPostProcessor 对 @Autowired 进行解析,所以要让 @Autowired 起作用必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。

修改在原来注入spirng容器中的bean的方法。

在域变量上加上标签@Autowired,并且去掉相应的get 和set方法

使用 @Autowired 注释的 Boss.java

importorg.springframework.beans.factory.annotation.Autowired;

public class Boss {

@Autowired

private Car car;

@Autowired

private Office office;

}

在applicatonContext.xml中把原来 引用的<porpery>标签也去掉。

<?xml version=”1.0″encoding=”UTF-8″ ?>

<beansxmlns=”http://www.springframework.org/schema/beans”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd”>

<!– 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 –>

<beanmargin: 0px; padding: 0px; color: rgb(0, 0, 0); font-family: Arial; font-size: 14px; line-height: 26px; background-color: rgb(255, 255, 255);”>       AutowiredAnnotationBeanPostProcessor”/>

<!– 移除 boss Bean 的属性注入配置的信息 –>

<bean id=”boss”/>

<bean id=”office”>

<property name=”officeNo” value=”001″/>

</bean>

<bean id=”car”scope=”singleton”>

<property name=”brand” value=” 红旗CA72″/>

<property name=”price” value=”2000″/>

</bean>

</beans>

这样,当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。

按照上面的配置,Spring 将直接采用 Java 反射机制对 Boss 中的 car 和 office 这两个私有成员变量进行自动注入。所以对成员变量使用 @Autowired 后,您大可将它们的 setter 方法(setCar() 和 setOffice())从 Boss 中删除。

当然,您也可以通过 @Autowired 对方法或构造函数进行标注,如果构造函数有两个入参,分别是 bean1 和 bean2,@Autowired 将分别寻找和它们类型匹配的 Bean,将它们作为 CountryService (Bean1 bean1 ,Bean2 bean2) 的入参来创建CountryService Bean。来看下面的对方法

public class Boss {

private Car car;

private Office office;

@Autowired

public void setCar(Car car) {

this.car = car;

}

@Autowired

public void setOffice(Office office) {

this.office = office;

}

}

这时,@Autowired 将查找被标注的方法的入参类型的 Bean,并调用方法自动注入这些 Bean。而下面的使用方法则对构造函数进行标注:

public class Boss {

private Car car;

private Office office;

@Autowired

public Boss(Car car ,Office office){

this.car = car;

this.office = office ;

}

}

由于 Boss() 构造函数有两个入参,分别是 car 和 office,@Autowired 将分别寻找和它们类型匹配的 Bean,将它们作为 Boss(Car car ,Office office) 的入参来创建 Boss Bean。

@Resource的作用和用法

@Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,面 @Resource 默认按 byName自动注入罢了。

@Resource 有两个属性是比较重要的,分别是 name和 type,Spring将 @Resource 注释的 name属性解析为 Bean的名字,

而 type属性则解析为 Bean的类型。所以如果使用 name属性,则使用 byName的自动注入策略,而使用 type属性时则使用 byType

自动注入策略。如果既不指定 name也不指定 type属性,这时将通过反射机制使用 byName自动注入策略。
Resource 注释类位于 Spring发布包的 lib/j2ee/common-annotations.jar类包中,因此在使用之前必须将其加入到项目的类库中。

来看一个使用 @Resource 的例子:

使用 @Resource注释的 Boss.java

importjavax.annotation.Resource;

public class Boss{

// 自动注入类型为 Car 的 Bean

@Resource

private Car car;    // 自动注入 bean 名称为 office 的 Bean

@Resource(name = “office”)

private Office office;

}

一般情况下,我们无需使用类似于 @Resource(type=Car.class) 的注释方式,因为 Bean 的类型信息可以通过 Java反射从代码中获取。
要让 JSR-250 的注释生效,除了在 Bean 类中标注这些注释外,还需要在 Spring容器中注册一个负责处理这些注释的BeanPostProcessor:

<bean/>

CommonAnnotationBeanPostProcessor 实现了 BeanPostProcessor 接口,它负责扫描使用了 JSR-250 注释的 Bean,并对它们进行相应的操作。

@Required注解用于检查特定的属性是否设置

1.RequiredAnnotationBeanPostProcessor 为该注解的处理器,即bean后置处理器,检查所有带有该解的bean属性是否设置,如果未设置则抛出异常。

2.在spring配置文件中可以通过<context:annotation-config/>元素自动注册RequiredAnnotationBeanPostProcessor处理器。

3.RequiredAnnotationBeanPostProcessor处理器还能自定义注解用于检查属性,功能与@Required一致

如:

1.定义一个注解类型

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomRequired {
}

2.配置RequiredAnnotationBeanPostProcessor,注入自定义注解类型

<bean>
<property name=”requiredAnnotationType”>
<value>CustomRequired</value>
</property>
</bean>

然后就可以使用@CustomRequired 检查属性是否设置,功能与@Required一致。

http://blog.csdn.net/yangxiaovip/article/details/18958363

Maven命令

没有评论

2015 年 10 月 16 日 at 下午 12:02分类:java | maven

Maven常用命令

执行maven的常用命令都需要从命令行进入到项目的根目录下执行.现列出maven的常用命令如下所示:

mvn clean  清空产生的项目命令

清空项目target目录下classes目录、test-classes目录下的class文件.

 

mvn eclipse:eclipse

将项目(java项目或者web项目)编程eclipse项目

 

mvn clean compile

编译项目命令

清空项目target目录下的classes目录下的class文件,并重新编译项目。

 

mvn clean test

执行测试用例命令

清空项目target目录下的classes目录下的test-classes文件,清空并执行测试用例。

 

mvn clean package 打包命令

默认将项目打包成jar包,也可以在pom文件中指定打包成其他包。如war包,打包成功后,war包输出到项目的target目录下。

 

mvn clean install 安装命令

将项目输出的war包或jar包安装到maven的本地仓库中。当执行这个命令后,其他的maven项目才能使用这个war包或jar包(特别是项目之前有依赖的)。

 

注意:执行mvn clean test命令的时候,会先执行mvn compile命令的,执行mvn clean package命令的时候,会先执行mvn compile和mvn test命令的,执行mvn clean install命令的时候,会先执行mvn clean package命令。

 

mvn tomcat:run  运行tomcat容器命令

mvnDebug tomcat:run  debug模式下运行tomcat容器命令

 

================================================

mvn compile  编译主程序源代码,不会编译test目录的源代码。第一次运行时,会下载相关的依赖包,可能会比较费时间。

 

mvn test-compile  编译测试代码,compile之会后生成target文件夹,主程序编译在classes下面,测试程序放在test-classes下。

 

mvn test 运行应用程序中的单元测试

 

mvn site 生成项目相关信息的网站

 

mvn clean 清除目标目录中的生成结果

 

mvn package 依据项目生成jar文件,打包之前会进行编译,测试。

 

mvn install 在本地Repository中安装jar。

 

mvn eclipse:eclipse

生成Eclipse项目文件及包引用定义,注意,需确保定义classpath variables:M2_REPO,指向本地maven类库目录。

 

 生成项目: 

mvn archetype:generate  列出所有可用的模板供选择并创建

 

mvn archetype:create -DgroupId=com.myproject.app -DartifactId=myproject -DpackageName=com.myproject.mavenbook

用archetype插件快速创建一个组名为com.myproject.app artifactId为myproject 项目包目录结构为com/myproject/mavenbook的java项目

 

mvn archetype:create -DgroupId=com.myproject.app -DartifactId=myproject -DpackageName=com.myproject.mavenbook -DarchetypeArtifactId=maven-archetype-webapp

用archetype插件快速创建一个组名为com.myproject.app artifactId为myproject 项目包目录结构为com/myproject/mavenbook的web-app项目

 

进入该目录发现有个pom.xml(以下简称pom)文件,mvn的全部配置(对于此项目)都在这了,通常开发需要集成到Eclipse,生成.project,.classpath

在pom-path下输入:

mvn eclipse:eclipse

 

 Maven dependency 插件:

 

mvn dependency:analyze  分析项目依赖性

mvn dependency:resolve  已解决依赖的列表

mvn dependency:tree   项目的整个依赖树

可以用来检查一下pom.xml 中下载下来的这些包之间的依赖关系是否正确

 

mvn install -X 查看完整的依赖踪迹,包含那些因为冲突或者其它原因而被拒绝引入的构件(慎用,输出信息巨大)

 

 Help插件

mvn help:effective-pom

查看项目的有效pom

 

mvn help:effective-pom > mypom.xml

可以把项目的有效pom放入mypom.xml里面去。以供查看

 

mvn help:active-profiles

列出活动的profile

mvn help:active-profiles

– 列出当前构建中活动的 Profile(项目的,用户的,全局的)。

 

mvn help:effective-pom

– 显示当前构建的实际 POM,包含活动的 Profile。

 

mvn help:effective-settings

– 打印出项目的实际 settings, 包括从全局的 settings 和用户级别 settings继承的配置。

 

mvn help:describe

– 描述插件的属性。它不需要在项目目录下运行。但是你必须提供你想要描述插件的 groupId 和 artifactId。

 

 

describe加上参数就会像下面这样:

mvn help:describe -Dcmd=install

mvn help:describe -Dcmd=help:describe

mvn help:describe -Dplugin=org.apache.maven.plugins:maven-help-plugin

mvn help:describe -DgroupId=org.apache.maven.plugins -DartifactId=maven-help-plugin

 

 

mvn test -Dtest=MyTest  只能src.test.java下的MyTest类进行测试

 

mvn test -Dtest=MyTest -DfailIfNoTests=false 如果测试类里没有测试方法不报错

 

mvn package -Dmavne.test.skip=true 打包之前不执行单元测试