JMC & Flight Recorder

‘JMC & Flight Recorder’ 从Java 7 Update 40之后,任务控制和Flight Recorder就将和JDK一起提供,正如InfoQ 在介绍它发布的新闻中所描述的那样。任务控制的出发点是监控、管理和排错,而Flight Recorder则是收集和评估性能数据的设施。这两个工具在JRockit中都已经存在,现在最终被移植到了HotSpot上 任务控制 任务控制提供的功能几乎和JVisual VM完全相同。这两个工具都能够连接到本地或者远程Java进程收集JMX数据。任务控制能够通过Java发现协议 (Java Discovery Protocol) 自动地发现远程运行的JVM。为了使用该功能JVM需要通过下面的参数启动: -Dcom.sun.management.jmxremote.autodiscovery=true -Dcom.sun.management.jdp.name=JVM_Name。 和JVisual VM相似的是,任务控制也有一个插件机制,能够进行定制化。但是与VisualVM不同的是,任务控制还能够在收集的数据上创建新的视图。现在能够使用的两个实验性的插件是JOverflow堆分析器 (查找低效的集合使用) 和DTrace记录器 (关联DTrace配置文件) 。任务控制拥有一个JMX浏览器作为它核心功能的一部分,同时提供了稍微更加强大的功能。例如,线程监控能够提供每一个线程的分配信息以及与堆栈跟踪相关的信息。因为任务控制是基于Eclipse平台的,所以它不仅能够作为JDK中的独立工具使用,还能够作为Eclipse插件从 Oracle任务控制更新网站上获取。 Flight Recorder Java Flight Recorder - JFR 默认被设置为关闭状态。JDK7 通过在启动应用程序的命令中加入-XX:+UnlockCommercialFeatures –XX:+FlightRecorder 参数来开启 JFR,以及相关的一些功能。但是值得注意的是这个命令只是开启了 JFR 功能,但并没有开启记录进程各种事件。 JDK 8 可能直接 通过jcmd控制JFR。 想要在JVM之外收集调试数据、特别是性能数据的工具需要实现JVMPI/JVMTI接口。虽然大部分分析工具发展的非常良好,但是让它们能够在产品中低消耗地运行依然是非常困难的。 Flight Recorder直接在JVM中实现了它自己的基于事件的监控接口,所以能够以最小的开销提供CPU时间或者对象分配分析这样的功能。例如,这个新接口允许采取线程的样本但不需要它们在还原点上,降低了开销和测量的偏差。只有少量使用字节码检测的事件对运行的代码有影响。大部分捕获技术是新的,第三方无法使用。Flight Recorder在JVM本地记录数据,但是是记录在堆外 (off-heap) ,因此它并不会影响内存特性和垃圾收集。当它被配置成持久化数据的时候,它会周期性地倾倒 (dump) 到一个文件中。 收集的数据主要包含4种类型的事件: “瞬间 (instant) “,在事件发生时进行记录;“可请求的 (requestable) “,它们会被轮循;“持续 (duration) “,表示一个时间间隔的度量;“定时的 (timed) “,它们和"持续"一样,但是对过滤数据应用了阀值。有两个预定义的配置: “连续性 (continuous) “,它的目的是始终运行;“剖析 (profiling) “,它会收集更多的数据以便进行短期分析。但是无论如何开销始终都非常低,除非明确地声明一个事件。 除了JVM生成的事件之外,还鼓励框架和应用程序服务器提供自己的事件。目前并不支持接口,但是Weblogic和Glassfish已经提供了事件,它们基本上成为了事实上的接口。Marcus Hirt在他的博客文章"使用 (非常不支持的) Java Flight Recorder API"中介绍了如何使用API。基本的步骤是扩展合适的Event类,通过添加注解表明值,然后从事件产生的代码中调用它。自定义的事件和其他事件并没有什么不同,也能够使用、创建仪表盘并随着其他的事件一起绘制。该版本包含的其他重要功能的细节信息可以从 Marcus Hirt的另一篇博客中找到。 ...

2015-05-19 · 1 min · 103 words · -

java vs javaw vs javaws

java vs javaw vs javaws http://javapapers.com/core-java/java-vs-javaw-vs-javaws/ This article gives an awareness tip. Do you know the difference between java, javaw and javaws tools. All these three are java application launchers. We know well about java.exe which we use quite often. Our command line friend, mostly we use it for convenience to execute small java programs. javaw is rare for us. Sometimes we have seen that in running application list in windows task manager. javaws is web start utility. ...

2015-01-22 · 3 min · 548 words · -

maven-compiler-plugin

maven-compiler-plugin maven-compiler-plugin 用于编译 java 源码, 3.0 以后的版本 默认用 javax.tools.JavaCompiler 编译 maven-compiler-plugin 3.6 和更高版本提供了一种新的配置方法 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>9</release> </configuration> </plugin> jdk 9 以上可以只声明 maven.compiler.release <properties> <maven.compiler.release>17</maven.compiler.release> </properties> <!-- ... --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> </plugin> </plugins> maven-compiler-plugin 从 3.6 开始可以只配置 <maven.compiler.release>, 来替代 maven.compiler.source and maven.compiler.target maven-compiler-plugin 会从 <properties> 里读取 maven.compiler.release, 可以不配置到 plugin>configuration 下 “maven.compiler.release” as an replacement for source and target http://blog.csdn.net/zhaoyongnj2012/article/details/23970451 在maven的默认配置中, 对于 jdk 的配置是 1.4 版本,那么创建/导入 maven 工程过程中, 工程中未指定 jdk版本。 ...

2014-12-30 · 1 min · 113 words · -

Java Callable, Future 和 FutureTask

Java Callable, Future 和 FutureTask 创建线程有两种方式,一种是直接继承 Thread,另外一种就是实现 Runnable 接口。 这两种方式都有一个缺陷就是: 在执行完任务之后无法获取执行结果。 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。 而自从Java 1.5 开始,JDK 提供了 Callable 和 Future, 通过它们可以在任务执行完毕之后得到任务执行结果。 今天我们就来讨论一下 Callable、Future 和 FutureTask 三个类的使用方法。以下是本文的目录大纲: Callable 与 Runnable Future FutureTask 使用示例 Callable 与 Runnable java.lang.Runnable 是一个接口,里面只声明了一个 run() 方法 public interface Runnable { public abstract void run(); } 由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。 Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做 call(): public interface Callable<V> { V call() throws Exception; } 可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。 那么怎么使用 Callable 呢? 一般情况下是配合 ExecutorService 来使用的,在 ExecutorService 接口中声明了若干个 submit 方法的重载版本: ...

2014-11-26 · 2 min · 396 words · -

java 对象

java 对象 http://www.jianshu.com/p/ebaa1a03c594 Java程序执行时,第一步系统创建虚拟机进程,然后虚拟器用类加载器Class Loader加载java程序类文件到方法区。 方法区放哪些东西? 存放加载过的类信息、常量、静态变量、及jit编译后的代码 (类方法) 等数据的内存区域。它是线程共享的。 方法区存放的信息包括: 类的基本信息、运行时常量池、变量字段信息、方法信息等。这部分的详细介绍看下面链接的文章。 详细Java程序运行的内存结构介绍 点此处 简要过程: 类加载完成后,主线程运行static main () 时在虚拟机栈中建栈帧,压栈。 执行到new Object () 时,在堆heap里创建对象。 对象创建的过程就是堆上分配实例对象内容空间的过程,在堆中对象内存空间的具体结构如下: 对象头 这个头包括两个部分,第一部分用于存储自身运行时的数据例如GC标志位、哈希码、锁状态等信息。第二部分存放指向方法区类静态数据的指针。 实例变量 存放类的属性数据信息,包括父类的属性信息。如果是数组的实例部分还包括数组的长度。这部分内存按4字节对齐。 填充数据 这是因为虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐。HotSpot VM的自动内存管理要求对象起始地址必须是8字节的整数倍。对象头本身是8的倍数,当对象的实例变量数据不是8的倍数,便需要填充数据来保证8字节的对齐。另外,堆上对象内存的分配是并发进行的. 然后执行类的构造函数初始化。 Java虚拟机规范规定该区域可抛出OutOfMemoryError。 详细步骤 例如: Dog dog= new Dog(); 当虚拟机执行到new指令时,它先在常量池中查找"Dog",看能否定位到Dog类的符号引用;如果能,说明这个类已经被加载到方法区了,则继续执行。如果没有,就让Class Loader先执行类的加载。 然后,虚拟机开始为该对象分配内存,对象所需要的内存大小在类加载完成后就已经确定了。这时候只要在堆中按需求分配空间即可。具体分配内存时有两种方式,第一种,内存绝对规整,那么只要在被占用内存和空闲内存间放置指针即可,每次分配空间时只要把指针向空闲内存空间移动相应距离即可,当某对象被GC回收后,则需要进行某些对象内存的迁移。第二种,空闲内存和非空闲内存夹杂在一起,那么就需要用一个列表来记录堆内存的使用情况,然后按需分配内存。 对于多线程的情况,如何确保一个线程分配了对象内存但尚未修改内存管理指针时,其他线程又分配该块内存而覆盖的情况?有一种方法,就是让每一个线程在堆中先预分配一小块内存 (TLAB本地线程分配缓冲) ,每个线程只在自己的内存中分配内存。但对象本身按其访问属性是可以线程共享访问的。 内存分配到后,虚拟机将分配的内存空间都初始化为零值(不包括对象头)。实例变量按变量类型初始化相应的默认值 (数值型为0,boolan为false) ,所以实例变量不赋初值也能使用。接着设置对象头信息,比如对象的哈希值,GC分代年龄等。 从虚拟机角度,此时一个新的对象已经创建完成了。但从我们程序运行的角度,新建对象才刚刚开始,对象的构造方法还没有执行。只有执行完构造方法,按构造方法进行初始化后,对象才是彻底创建完成了。 构造函数的执行还涉及到调用父类构造器,如果没有显式声明调用父类构造器,则自动添加默认构造器。 到此,new运算符可以返回堆中这个对象的引用了。 此刻,会根据dog这个变量是实例变量、局部变量或静态变量的不同将引用放在不同的地方: 如果dog局部变量,dog变量在栈帧的局部变量表,这个对象的引用就放在栈帧。 如果dog是实例变量,dog变量在堆中,对象的引用就放在堆。 如果dog是静态变量,dog变量在方法区,对象的引用就放在方法区。 Java有三种方法可以创建对象实例。 new 通常都是使用java的关键字new来创建对象实例。 若有一个Something类,则可以通过下面的语句创建Something类的对象实例并指定到变量obj。 Something something New = new Something(); 通过new创建对象实例必须把类名写在原代码里面。 clone 若程序写成如下,则可以根据当前对象 (this) 建立一个新实例对象 (没有调用构造函数) . ...

2014-11-19 · 2 min · 271 words · -

Google Guava

Google Guava Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这些高质量的 API 可以使你的JAVa代码更加优雅,更加简洁,让你工作更加轻松愉悦。下面我们就开启优雅Java编程学习之旅! **项目相关信息: ** 官方首页: http://code.google.com/p/guava-libraries 官方下载: http://code.google.com/p/guava-libraries/downloads/list 官方文档: http://docs.guava-libraries.googlecode.com/git/javadoc http://www.ostools.net/apidocs/apidoc?api=guava **源码包的简单说明: ** com.google.common.annotations: 普通注解类型。 com.google.common.base: 基本工具类库和接口。 com.google.common.cache: 缓存工具包,非常简单易用且功能强大的JVM内缓存。 com.google.common.collect: 带泛型的集合接口扩展和实现,以及工具类,这里你会发现很多好玩的集合。 com.google.common.eventbus: 发布订阅风格的事件总线。 com.google.common.hash: 哈希工具包。 com.google.common.io: I/O工具包。 com.google.common.math: 原始算术类型和超大数的运算工具包。 com.google.common.net: 网络工具包。 com.google.common.primitives: 八种原始类型和无符号类型的静态工具包。 com.google.common.reflect: 反射工具包。 com.google.common.util.concurrent: 多线程工具包。 **类库使用手册: ** **一. 基本工具类: **让使用Java语言更令人愉悦。 使用和避免 null: null 有语言歧义, 会产生令人费解的错误, 反正他总是让人不爽。很多 Guava 的工具类在遇到 null 时会直接拒绝或出错,而不是默默地接受他们。 前提条件: 更容易的对你的方法进行前提条件的测试。 ...

2014-11-12 · 1 min · 211 words · -

Google Guava

Google Guava Guava 是一个 Google 的基于java1.6的类库集合的扩展项目,包括 collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, 等等. 这些高质量的 API 可以使你的JAVa代码更加优雅,更加简洁,让你工作更加轻松愉悦。下面我们就开启优雅Java编程学习之旅! **项目相关信息: ** 官方首页: http://code.google.com/p/guava-libraries 官方下载: http://code.google.com/p/guava-libraries/downloads/list 官方文档: http://docs.guava-libraries.googlecode.com/git/javadoc http://www.ostools.net/apidocs/apidoc?api=guava **源码包的简单说明: ** com.google.common.annotations: 普通注解类型。 com.google.common.base: 基本工具类库和接口。 com.google.common.cache: 缓存工具包,非常简单易用且功能强大的JVM内缓存。 com.google.common.collect: 带泛型的集合接口扩展和实现,以及工具类,这里你会发现很多好玩的集合。 com.google.common.eventbus: 发布订阅风格的事件总线。 com.google.common.hash: 哈希工具包。 com.google.common.io: I/O工具包。 com.google.common.math: 原始算术类型和超大数的运算工具包。 com.google.common.net: 网络工具包。 com.google.common.primitives: 八种原始类型和无符号类型的静态工具包。 com.google.common.reflect: 反射工具包。 com.google.common.util.concurrent: 多线程工具包。 **类库使用手册: ** **一. 基本工具类: **让使用Java语言更令人愉悦。 使用和避免 null: null 有语言歧义, 会产生令人费解的错误, 反正他总是让人不爽。很多 Guava 的工具类在遇到 null 时会直接拒绝或出错,而不是默默地接受他们。 前提条件: 更容易的对你的方法进行前提条件的测试。 ...

2014-11-12 · 1 min · 211 words · -

java openjdk JMH

java openjdk JMH create test project with maven mvn archetype:generate \ -DinteractiveMode=false \ -DarchetypeGroupId=org.openjdk.jmh \ -DarchetypeArtifactId=jmh-java-benchmark-archetype \ -DgroupId=org.sample \ -DartifactId=test \ -Dversion=1.0 JMH 是一个由 OpenJDK/Oracle 里面那群开发了 Java 编译器的大牛们所开发的 Micro Benchmark Framework 。何谓 Micro Benchmark 呢?简单地说就是在 method 层面上的 benchmark,精度可以精确到微秒级。可以看出 JMH 主要使用在当你已经找出了热点函数,而需要对热点函数进行进一步的优化时,就可以使用 JMH 对优化的效果进行定量的分析。 比较典型的使用场景还有: 想定量地知道某个函数需要执行多长时间,以及执行时间和输入 n 的相关性 一个函数有两种不同实现 (例如实现 A 使用了 FixedThreadPool,实现 B 使用了 ForkJoinPool) ,不知道哪种实现性能更好 尽管 JMH 是一个相当不错的 Micro Benchmark Framework,但很无奈的是网上能够找到的文档比较少,而官方也没有提供比较详细的文档,对使用造成了一定的障碍。但是有个好消息是官方的 Code Sample 写得非常浅显易懂,推荐在需要详细了解 JMH 的用法时可以通读一遍——本文则会介绍 JMH 最典型的用法和部分常用选项。 第一个例子 如果你使用 maven 来管理你的 Java 项目的话,引入 JMH 是一件很简单的事情——只需要在 pom.xml 里增加 JMH 的依赖即可 <jmh.version>1.14.1</jmh.version> ...

2014-09-03 · 5 min · 866 words · -

HashSet, TreeSet, LinkedHashSet

HashSet, TreeSet, LinkedHashSet 在一个set中,是没有重复元素的。这也是使用set最主要的原因之一。Set的实现类有三个: HashSet,TreeSet,LinkedHashSet。什么时候使用哪一种实现类?。简单地说,如果我们想要一个快速的set,那么我们应该使用HashSet;如果我们需要一个已经排好序的set,那么TreeSet应该被使用;如果我们想一个可以根据插入顺序来读取的set,那么LinkedHashSet应该被使用。 接口 Set接口继承了Collection接口。在set中,不允许有重复的元素。每一个元素在set中都是唯一的。我们可以简单地添加元素至一个set中,最后,我们会得到一个自动删除重复元素的set。 HashSet vs. TreeSet vs. LinkedHashSet HashSet 是使用一个哈希表实现的。元素是无序的。add、remove 及contains 方法的时间复杂度是一个常量 O(1)。 TreeSet 是使用红黑树 来实现的。元素在set中被排好序,但是add、remove及contains方法的时间复杂度为O(log(n))。它提供了几个方法用来处理有序的set,比如first(),last(),headSet(),tailSet()等等。 LinkedHashSet LinkedHashSet介于HashSet与TreeSet之间。它由一个执行hash表的链表实现,因此,它提供顺序插入。基本方法的时间复杂度为O(1)。 HashMap和HashSet的区别是Java面试中最常被问到的问题。如果没有涉及到Collection框架以及多线程的面试,可以说是不完整。而Collection框架的问题不涉及到HashSet和HashMap,也可以说是不完整。HashMap和HashSet都是collection框架的一部分,它们让我们能够使用对象的集合。collection框架有自己的接口和实现,主要分为Set接口,List接口和Queue接口。它们有各自的特点,Set的集合里不允许对象有重复的值,List允许有重复,它对集合中的对象进行索引,Queue的工作原理是FCFS算法(First Come, First Serve)。 首先让我们来看看什么是HashMap和HashSet,然后再来比较它们之间的分别。 什么是HashSet HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现。 public boolean add(Object o)方法用来在Set中添加元素,当元素值重复时则会立即返回false,如果成功添加的话会返回true。 什么是HashMap HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许重复的键。Map接口有两个基本的实现,HashMap和TreeMap。TreeMap保存了对象的排列次序,而HashMap则不能。HashMap允许键和值为null。HashMap是非synchronized的,但collection框架提供方法能保证HashMap synchronized,这样多个线程同时访问HashMap时,能保证只有一个线程更改Map。 public Object put(Object Key,Object value)方法用来将元素添加到map中。 HashSet和HashMap的区别 对于HashSet而言,它的底层是基于HashMap实现的。HashSet底层使用HashMap来保存所有元素。 HashSet的实现其实非常简单,它只是封装了一个HashMap对象来存储所有的集合元素。所有放入HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储了一个PRESENT,它是一个静态的Object对象。 HashSet的绝大部分方法都是通过调用HashMap的方法来实现的,因此HashSet和HashMap两个集合在实现本质上是相同的。 注意:由于HashSet的add()方法添加集合元素实际上转变为调用HashMap的put()方法来添加key-value对,当新放入HashMap的Entry中key与集合中原有Entry的key相同 (hashCode()返回值相等,通过equals比较也返回true)时,新添加的Entry的value将覆盖原来Entry的value,但key不会有任何改变。因此,如果向HashSet中添加一个已经存在的元素,新添加的集合元素 (底层由HashMap的key保存)不会覆盖已有的集合元素。 ———————————————— 版权声明:本文为CSDN博主「bear_wr」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/bear_wr/article/details/52275874

2014-06-17 · 1 min · 53 words · -

maven setting, mirror, repository

maven setting, mirror, repository maven mirror, repository mirror和 repository 1 Repository (仓库) 1.1 Maven仓库主要有2种: remote repository: 相当于公共的仓库,大家都能访问到,一般可以用URL的形式访问 local repository: 存放在本地磁盘的一个文件夹,例如,windows上默认是C:\Users\{用户名}.m2\repository目录 1.2 Remote Repository主要有3种: 中央仓库: http://repo1.maven.org/maven2/ 私服: 内网自建的maven repository,其URL是一个内部网址 其他公共仓库: 其他可以互联网公共访问maven repository,例如 jboss repository等 repository里存放的都是各种jar包和maven插件。当向仓库请求插件或依赖的时候,会先检查local repository,如果local repository有则直接返回,否则会向remote repository请求,并缓存到local repository。也可以把做的东西放到本地仓库,仅供本地使用;或上传到远程仓库,供大家使用。 2 Mirror mirror相当于一个拦截器,它会拦截maven对remote repository的相关请求,把请求里的remote repository地址,重定向到mirror里配置的地址。 2.1 没有配置mirror: 2.2 配置mirror: 此时,B Repository被称为A Repository的镜像。 如果仓库X可以提供仓库Y存储的所有内容,那么就可以认为X是Y的一个镜像。换句话说,任何一个可以从仓库Y获得的构件,都胡够从它的镜像中获取。 2.3 标签里面放置的是要被镜像的Repository ID。为了满足一些复杂的需求,Maven还支持更高级的镜像配置: ...

2014-05-18 · 2 min · 217 words · -

java version

java version Java class file format major version numbers Java 1.2 uses major version 46 Java 1.3 uses major version 47 Java 1.4 uses major version 48 Java 5 uses major version 49 Java 6 uses major version 50 Java 7 uses major version 51 Java 8 uses major version 52 Java 9 uses major version 53 Java 10 uses major version 54 Java 11 uses major version 55 Java 12 uses major version 56 Java 13 uses major version 57 Java 14 uses major version 58 Java 15 uses major version 59 Java 16 uses major version 60 Java 17 uses major version 61

2014-05-13 · 1 min · 105 words · -

instanceof

instanceof Java中的instanceof关键字是一个二元操作符,和==,>,<是同一类东西。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。举个例子: String s = "I AM an Object!"; boolean isObject = s instanceof Object; 我们声明了一个String对象引用,指向一个String对象,然后用instancof来测试它所指向的对象是否是Object类的一个实例,显然,这是真的,所以返回true,也就是isObject的值为True。 instanceof有一些用处。比如我们写了一个处理账单的系统,其中有这样三个类: public class Bill {//省略细节} public class PhoneBill extends Bill {//省略细节} public class GasBill extends Bill {//省略细节} 在处理程序里有一个方法,接受一个Bill类型的对象,计算金额。假设两种账单计算方法不同,而传入的Bill对象可能是两种中的任何一种,所以要用instanceof来判断: public double calculate(Bill bill) { if (bill instanceof PhoneBill) { //计算电话账单 } if (bill instanceof GasBill) { //计算燃气账单 } … } 这样就可以用一个方法处理两种子类。 然而,这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现,这是面向对象变成应有的做法,避免回到结构化编程模式。只要提供两个名字和返回值都相同,接受参数类型不同的方法就可以了: public double calculate(PhoneBill bill) { //计算电话账单 } public double calculate(GasBill bill) { //计算燃气账单 } 所以,使用instanceof在绝大多数情况下并不是推荐的做法,应当好好利用多态。 http://rodney.cnblogs.com/archive/2005/08/18/instanceof.html instanceof 判断对象类型 当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生ClassCastException异常,所以在执行向下转型之前需要养成一个良好习惯,就是判断父类对象是否为子类对象的实例。这个判断通常使用instanceof操作符来完成。可以使用instanceof操作符判断是否一个类实现了某个接口 (接口会在10.6节中进行介绍) ,也可以用它来判断一个实例对象是否属于一个类。 instanceof的语法格式如下: myobject instanceof ExampleClass ...

2014-05-09 · 1 min · 154 words · -

spring annotation

spring annotation @Component;@Controller;@Service;@Repository @Component 在annotaion配置注解中用 @Component 来表示一个通用注释用于说明一个类是一个spring容器管理的类。即就是该类已经纳入到spring的管理中了。而@Controller, @Service, @Repository是 @Component 的细化,这三个注解比 @Component 带有更多的语义,它们分别对应了控制层、服务层、持久层的类。 @Service @Service 用于标注业务层组件,对象名默认是类名 (头字母小写), 如果想自定义,可以@Service(“foo”)这样来指定,这种bean默认是单例的,如果想改变,可以使用@Service(“foo”) @Scope(“prototype”)来改变。 @Controller用于标注控制层组件 (如struts中的action) @Repository用于标注数据访问组件,即DAO组件 @Component 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 @Autowired Spring自己定义的注解, JSR-250规范定义的注解 @Resource @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入 @Value 将外部的值动态注入到Bean中 @Value("normal") private String normal; // 注入普通字符串 @Value("#{systemProperties['os.name']}") private String systemPropertiesName; // 注入操作系统属性 @Value("#{ T(java.lang.Math).random() * 100.0 }") private double randomNumber; //注入表达式结果 @Value("#{beanInject.another}") private String fromAnotherBean; // 注入其他Bean属性: 注入beanInject对象的属性another,类具体定义见下面 @Value("classpath:com/hry/spring/configinject/config.txt") private Resource resourceFile; // 注入文件资源 @Value("http://www.baidu.com") private Resource testUrl; // 注入URL资源 @PostConstruct 注解在方法上,表示此方法是在Spring实例化该Bean之后马上执行此方法,之后才会去实例化其他Bean,并且一个Bean中@PostConstruct注解的方法可以有多个。 ...

2014-04-30 · 1 min · 79 words · -

maven jvm opts

maven jvm opts Maven工程的JVM配置方式 为Maven运行配置JVM参数 这种需求比较少见,一般使用默认的JVM配置即可。如果需要,可以通过设置环境变量来满足需求,如: Windows下添加环境变量MAVEN_OPTS的value为-Xms1024m -Xmx1024m -Xss1m Linux下可修改.profile或者.bash_profile文件,并做如下设置: export MAVEN_OPTS="-Xms1024m -Xmx1024m -Xss1m" (注意: 这里需要使用双引号或者单引号)

2014-04-24 · 1 min · 16 words · -

Jackson

Jackson Jackson 框架,轻易转换JSON Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。 前面有介绍过json-lib这个框架,在线博文: http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html 相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。而且Jackson社区相对比较活跃,更新速度也比较快。 一、准备工作 下载依赖库jar包 Jackson的jar all下载地址: http://jackson.codehaus.org/1.7.6/jackson-all-1.7.6.jar 然后在工程中导入这个jar包即可开始工作 官方示例: http://wiki.fasterxml.com/JacksonInFiveMinutes 因为下面的程序是用junit测试用例运行的,所以还得添加junit的jar包。版本是junit-4.2.8 如果你需要转换xml,那么还需要stax2-api.jar 测试类基本代码如下 package com.hoo.test; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.JsonNodeFactory; import org.codehaus.jackson.xml.XmlMapper; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.AccountBean; /** function:Jackson 将java对象转换成JSON字符串,也可以将JSON字符串转换成java对象 jar-lib-version: jackson-all-1.6.2 jettison-1.0.1 @author hoojo @createDate 2010-11-23 下午04:54:53 ...

2014-04-04 · 9 min · 1809 words · -

java 内部类, 静态内部类, inner class

java 内部类, 静态内部类, inner class 内部类 public class OuterClass { private String name; private int age; class InnerClass { public InnerClass(){ name = "mark"; age = 20; } public void echo() { System.out.println(name + " " + age); } } } 问题思考 上面这个很简单的例子中,也包含了很多应该思考的问题: 内部类如何被实例化? 内部类能否改变外围类的属性,两者之间又是什么一种关系? 内部类存在的意义是什么? 在回答这三个问题之前,必须要明确一个点,那就是内部类是依附于外围类而存在的,其实也就是内部类存在着指向外围类的引用。明白了这个之后,上面的问题就好解答了。 实例化与数据访问 内部类与外围类之间形成了一种联系,使得内部类可以无限制地访问外围类中的任意属性。 正如上面的例子中,InnerClass内部可以随意访问OuterClass中的private属性。 同样的,因为内部类依赖与外围类的存在,所以无法在外部直接将其实例化,而是必须先实例化外围类,才能够实例化内部类 (注意,在外围类的成员方法里仍然是可以直接实例化内部类的): public static void main(String[] args) { InnerClass inner = new OuterClass().new InnerClass(); inner.echo(); } 复制代码使用外围类的.new来创建外部类。 我们也知道,内部类和外围类的联系是通过内部类所持有的外部类的引用来实现的,想要获取这个引用,可以使用外围类的.this来实现,可以参考下面这个测试用例 public class OuterClass { private String name; private int age; class InnerClass { public InnerClass(){ name = “mark”; age = 20; } public void echo() { System.out.println(name + " " + age); } public OuterClass getOuter() { return OuterClass.this; } } ...

2014-04-04 · 5 min · 876 words · -

java – volatile

java – volatile volatile 关键字, Volatile [‘vɑlətl] volatile关键字告诉编译器,去内存里面取最新值。但是,即使取的是内存里的所谓“最新”值,事实上并不能保证最新。 voldatile关键字首先具有“易变性”,声明为volatile变量编译器会强制要求读内存,相关语句不会直接使用上一条语句对应的的寄存器内容,而是重新从内存中读取。 其次具有”不可优化”性,volatile告诉编译器,不要对这个变量进行各种激进的优化,甚至将变量直接消除,保证代码中的指令一定会被执行。 最后具有“顺序性”,能够保证Volatile变量间的顺序性,编译器不会进行乱序优化。不过要注意与非volatile变量之间的操作,还是可能被编译器重排序的。 需要注意的是其含义跟原子操作无关,比如: volatile int a; a++; 其中a++操作实际对应三条汇编指令实现”读-改-写“操作 (RMW) ,并非原子的。 思考: bool 类型是不是适合使用, 不会出问题。 不同编程语言中 voldatile 含义与实现并不完全相同, Java 语言中 voldatile 变量可以被看作是一种轻量级的同步, 因其还附带了 acuire 和 release 语义。 实际上也是从 JDK5 以后才通过这个措施进行完善,其 volatile 变量具有 synchronized 的可见性特性, 但是不具备原子特性。 Java语言中有 volatile 修饰的变量, 赋值后多执行了一个 load addl $0x0, (%esp) 操作, 这个操作相当于一个 lock 指令, 就是增加一个完全的内存屏障指令, 这点与C++实现并不一样。 volatile 的读性能消耗与普通变量几乎相同, 但是写操作稍慢 ,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。 Java 实践中仅满足下面这些条件才应该使用 volatile 关键字: 变量写入操作不依赖变量当前值,或确保只有一个线程更新变量的值 (Java可以,C++仍然不能) 该变量不会与其他变量一起纳入 变量并未被锁保护 C++中voldatile等于插入编译器级别屏障,因此并不能阻止CPU硬件级别导致的重排。C++11 中volatile语义没有任何变化,不过提供了std::atomic工具可以真正实现原子操作,而且默认加入了内存屏障 (可以通过在store与load操作时设置内存模型参数进行调整,默认为std::memory_order_seq_cst) 。 ...

2014-02-12 · 3 min · 533 words · -

META-INF, MANIFEST.MF

META-INF, MANIFEST.MF 做过 JAVA EE 开发的工程师应该都知道在 JAVA build 出来的 JAR 或者 WAR 的顶层目录下有个 META-INF 文件夹吧,可是有多少人能够清楚说出这个文件夹到底是做神马的? What is the purpose of META-INF? 恐怕不是都能说的清楚准确吧。 把这个问题抛出来,是因为我在公司的项目中发现 META-INF 这个文件夹被误用了,看来不是每个人都清楚 :) 所谓 META-INF, 说白了就是存放一些 meta information 相关的文件的这么一个文件夹, 一般来说尽量不要自己手工放置文件到这个文件夹。怎么理解这句话呢? 就是说这个文件夹应该被看作是 JAVA 工程的一个内部 META 目录,所以这个目录下的文件应该都是 build 工具来生成的。我们自己的文件应该直接放到根目录下或者其他的子目录中。 根据官方的 JAR file specification (http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html), 一个典型的 META-INF 目录下可能包含如下几种文件或者子目录: MANIFEST.MF: The manifest file that is used to define extension and package related data. INDEX.LIST x.SF x.DSA services/ 不过理想和现实总是有差距,现在即使一些著名的开源代码对 META-INF 的使用上都存在大的差异,类似 Apache CXF 中就有这样的Spring配置: ...

2014-01-01 · 1 min · 95 words · -

Class.forName

Class.forName Class类简介: Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。 Class 没有公共构造方法。Class 对象是在加载类时由Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。 虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类 (型) 都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。 基本的 Java 类型 (boolean、byte、char、short、int、long、float 和 double) 和关键字 void 也都对应一个 Class 对象。 每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。 一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。 一、如何得到Class的对象呢?有三种方法可以的获取: 1、调用Object类的getClass()方法来得到Class对象,这也是最常见的产生Class对象的方法。例如: MyObject x; Class c1 = x.getClass(); 2、使用Class类的中静态forName()方法获得与字符串对应的Class对象。例如: Class c2=Class.forName(“MyObject”),Employee必须是接口或者类的名字。 获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。例如 Class cl1 = Manager.class; Class cl2 = int.class; Class cl3 = Double[].class; 注意: Class对象实际上描述的只是类型,而这类型未必是类或者接口。例如上面的int.class是一个Class类型的对象。由于历史原因,数组类型的getName方法会返回奇怪的名字。 二、Class类的常用方法 getName() 一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体 (类、接口、数组类、基本类型或 void) 名称。 newInstance() Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如: x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器 (无参数构造器) 初始化新建对象。 ...

2013-12-21 · 4 min · 841 words · -

阻塞队列 BlockingQueue

阻塞队列 BlockingQueue 什么是阻塞队列 阻塞队列 (BlockingQueue) 是一个支持两个附加操作的队列。这两个附加的操作是: 在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。 方法\处理方式 抛出异常 返回特殊值 一直阻塞 超时退出 插入方法 add(e) offer(e) put(e) offer(e,time,unit) 移除方法 remove() poll() take() poll(time,unit) 检查方法 element() peek() 不可用 不可用 抛出异常: 是指当阻塞队列满时候,再往队列里插入元素,会抛出IllegalStateException(“Queue full”)异常。当队列为空时,从队列里获取元素时会抛出NoSuchElementException异常 。 返回特殊值: 插入方法会返回是否成功,成功则返回true。移除方法,则是从队列里拿出一个元素,如果没有则返回null 一直阻塞: 当阻塞队列满时,如果生产者线程往队列里put元素,队列会一直阻塞生产者线程,直到拿到数据,或者响应中断退出。当队列空时,消费者线程试图从队列里take元素,队列也会阻塞消费者线程,直到队列可用。 超时退出: 当阻塞队列满时,队列会阻塞生产者线程一段时间,如果超过一定的时间,生产者线程就会退出。 Java里的阻塞队列 JDK7 提供了 7 个阻塞队列 ArrayBlockingQueue : 一个由数组结构组成的有界阻塞队列。 LinkedBlockingQueue : 一个由链表结构组成的有界阻塞队列。 PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列。 DelayQueue: 一个使用优先级队列实现的无界阻塞队列。 SynchronousQueue: 一个不存储元素的阻塞队列。 LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。 LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。 在JDK1.5新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全"传输"数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。 认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出; 常用的队列主要有以下两种: (当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种) 先进先出 (FIFO) : 先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。 后进先出 (LIFO) : 后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。 ...

2013-12-20 · 3 min · 447 words · -