计算机科学精彩帖子收集--JAVA和分布式专栏


之前收集了一个计算机科学精彩帖子收集,渐渐发现帖子越来越大,所以现在干脆把Java和分布式的部分单独一贴。


Java

jdk下载

http://openjdk.java.net/projects/jdk8/

----------------------------------------

Eclipse

eclipse颜色插件 color theme

myeclipse配置jdk

Eclipse自动部署项目到Tomcat的webapps下的有效方法   【重要,一定要看】

Eclipse自动部署项目到Tomcat的webapps下的有效方法   [和上面一样,纯备份]

Eclipse调试Java的10个技巧

Java heap dump触发和分析(转)

使用$JAVA_HOME/bin/jmap -dump来触发, Eclipse Memory Analyzer是一个快速并且功能强大的Java heap分析器,能够帮助你查找内存泄漏和减少内存消耗。

Eclipse debug技巧

Eclipse调试Java代码

Eclipse中的条件断点

最详细eclipse汉化插件安装教程

Eclipse怎样配置struts2?[成功配置]

在Eclipse中配置Struts2

一、Eclipse helios 配置struts2图解

Eclipse下搭建Struts2环境

在Eclipse中配置Struts2项目(二)  [讲了JDK,和Tomcat的配置以及struts虽然是2007年写的不过很好]

eclipse中配置jdk

Eclipse.ini的相关说明

eclipse配置java虚拟机的方法

全面认识Eclipse中JVM内存设置

MyEclipse设置默认的JSP页面打开方式

Myeclipse中如何更改jsp默认的打开方式

Java Code Review清单

===============【JVM】==================

内存详解 理解 JVM 如何使用 Windows 和 Linux 上的本机内存

Java™ 堆耗尽并不是造成 java.lang.OutOfMemoryError 的惟一原因。如果本机内存 耗尽,则会发生普通调试技巧无法解决的 OutOfMemoryError。

当出现 java.lang.OutOfMemoryError 或看到有关内存不足的错误消息时,要做的第一件事是确定哪种类型的内存被耗尽。
最简单的方式是首先检查 Java 堆是否被填满。如果 Java 堆未导致 OutOfMemory 条件,那么您应该分析本机堆使用情况。

内核空间和用户空间
作为计算机启动序列的一部分,操作系统内核运行并初始化硬件。一旦内核配置了硬件及其自己的内部状态,第一个用户空间进程就会启动。
如果用户程序需要来自操作系统的服务,它可以执行一种称为系统调用 的操作与内核程序交互,内核程序然后执行该请求。
系统调用通常是读取和写入文件、联网和启动新进程等操作所必需的。


当执行系统调用时,内核需要访问其自己的内存和调用进程的内存。操作系统必须在地址空间之间复制数据并重置进程地址-空间映射。

使用 32 位 Java 运行时很容易遇到本机内存耗尽的情况,因为地址空间相对较小。32 位操作系统提供的 2 到 4GB 用户空间通常小于系统附带的物理内存量,而且现代的数据密集型应用程序很容易耗尽可用空间。
如果您运行的是 64 位操作系统,那么 64 位 Java 运行时将能够满足海量 Java 堆的需求,还会减少与地址空间相关的问题。64 位操作系统上目前可用的用户空间。

移动到 64 位并不是所有本机内存问题的通用解决方案,您仍然需要足够的物理内存来持有所有数据。
如果物理内存不够 Java 运行时使用,运行时性能将变得非常糟,因为操作系统不得不在内存与交换空间之间来回复制 Java 运行时数据。
出于相同原因,移动到 64 位也不是内存泄漏永恒的解决方案,您只是提供了更多空间来供泄漏,这只会延缓您不得不重启应用程序的时间。

在设计和运行大型 Java 应用程序时,理解本机内存至关重要,但是这一点通常被忽略,因为它与复杂的硬件和操作系统细节密切相关,Java 运行时的目的正是帮助我们规避这些细节。
JRE 是一个本机进程,它必须在由这些纷繁复杂的细节定义的环境中工作。要从 Java 应用程序中获得最佳的性能,您必须理解应用程序如何影响 Java 运行时的本机内存使用。
耗尽本机内存与耗尽 Java 堆很相似,但它需要不同的工具集来调试和解决。修复本机内存问题的关键在于理解运行您的 Java 应用程序的硬件和操作系统施加的限制,并将其与操作系统工具知识结合起来,监控本机内存使用。通过这种方法,您将能够解决 Java 应用程序产生的一些非常棘手的问题。

Java 运行时如何使用本机内存
Java 运行时是一个操作系统进程,它会受到硬件和操作系统局限性的限制。
Java 堆是分配了对象的内存区域。
当使用的堆区域缩小时,一些垃圾收集器会回收堆的一部分(释放堆的后备存储空间),从而减少使用的物理内存。


即时 (JIT) 编译器
JIT 编译器在运行时编译 Java 字节码来优化本机可执行代码。这极大地提高了 Java 运行时的速度,并且支持 Java 应用程序以与本机代码相当的速度运行。
字节码编译使用本机内存(使用方式与 gcc 等静态编译器使用内存来运行一样),但 JIT 编译器的输入(字节码)和输出(可执行代码)必须也存储在本机内存中。包含多个经过 JIT 编译的方法的 Java 应用程序会使用比小型应用程序更多的本机内存。


类和类加载器
Java 应用程序由一些类组成,这些类定义对象结构和方法逻辑。Java 应用程序也使用 Java 运行时类库(比如 java.lang.String)中的类,也可以使用第三方库。这些类需要存储在内存中以备使用。
存储类的方式取决于具体实现。Sun JDK 使用永久生成(permanent generation,PermGen)堆区域。


从最基本的层面来看,使用更多的类将需要使用更多内存。(这可能意味着您的本机内存使用量会增加,或者您必须明确地重新设置 PermGen 或共享类缓存等区域的大小,以装入所有类)。
记住,不仅您的应用程序需要加载到内存中,框架、应用服务器、第三方库以及包含类的 Java 运行时也会按需加载并占用空间。


Java 运行时可以卸载类来回收空间,但是只有在非常严酷的条件下才会这样做。不能卸载单个类,而是卸载类加载器,随其加载的所有类都会被卸载。


需要注意的是,Java 运行时为所有 Java 应用程序创建的 3 个默认类加载器( bootstrap、extension 和 application )都不可能满足这些条件,
因此,任何系统类(比如 java.lang.String)或通过应用程序类加载器加载的任何应用程序类都不能在运行时释放。


即使类加载器适合进行收集,运行时也只会将收集类加载器作为 GC 周期的一部分。一些实现只会在某些 GC 周期中卸载类加载器。
也可能在运行时生成类,而不用释放它。许多 JEE 应用程序使用 JavaServer Pages (JSP) 技术来生成 Web 页面。使用 JSP 会为执行的每个 .jsp 页面生成一个类,并且这些类会在加载它们的类加载器的整个生存期中一直存在 —— 这个生存期通常是 Web 应用程序的生存期。
另一种生成类的常见方法是使用 Java 反射。反射的工作方式因 Java 实现的不同而不同


JNI
JNI 支持本机代码(使用 C 和 C++ 等本机编译语言编写的应用程序)调用 Java 方法,反之亦然。Java 运行时本身极大地依赖于 JNI 代码来实现类库功能,比如文件和网络 I/O。JNI 应用程序可能通过 3 种方式增加 Java 运行时的本机内存占用:
JNI 应用程序的本机代码被编译到共享库中,或编译为加载到进程地址空间中的可执行文件。大型本机应用程序可能仅仅加载就会占用大量进程地址空间。
本机代码必须与 Java 运行时共享地址空间。任何本机代码分配或本机代码执行的内存映射都会耗用 Java 运行时的内存。
某些 JNI 函数可能在它们的常规操作中使用本机内存。GetTypeArrayElements 和 GetTypeArrayRegion 函数可以将 Java 堆数据复制到本机内存缓冲区中,以供本机代码使用。是否复制数据依赖于运行时实现。(IBM Developer Kit for Java 5.0 和更高版本会进行本机复制)。通过这种方式访问大量 Java 堆数据可能会使用大量本机堆。


NIO
Java 1.4 中添加的新 I/O (NIO) 类引入了一种基于通道和缓冲区来执行 I/O 的新方式。就像 Java 堆上的内存支持 I/O 缓冲区一样,NIO 添加了对直接 ByteBuffer 的支持(使用 java.nio.ByteBuffer.allocateDirect() 方法进行分配), ByteBuffer 受本机内存而不是 Java 堆支持。直接 ByteBuffer 可以直接传递到本机操作系统库函数,以执行 I/O — 这使这些函数在一些场景中要快得多,因为它们可以避免在 Java 堆与本机堆之间复制数据。
对于在何处存储直接 ByteBuffer 数据,很容易产生混淆。应用程序仍然在 Java 堆上使用一个对象来编排 I/O 操作,但持有该数据的缓冲区将保存在本机内存中,Java 堆对象仅包含对本机堆缓冲区的引用。非直接 ByteBuffer 将其数据保存在 Java 堆上的 byte[] 数组中。


直接 ByteBuffer 对象会自动清理本机缓冲区,但这个过程只能作为 Java 堆 GC 的一部分来执行,因此它们不会自动响应施加在本机堆上的压力。GC 仅在 Java 堆被填满,以至于无法为堆分配请求提供服务时发生,或者在 Java 应用程序中显式请求它发生(不建议采用这种方式,因为这可能导致性能问题)。
发生垃圾收集的情形可能是,本机堆被填满,并且一个或多个直接 ByteBuffers 适合于垃圾收集(并且可以被释放来腾出本机堆的空间),但 Java 堆几乎总是空的,所以不会发生垃圾收集。


线程
应用程序中的每个线程都需要内存来存储器堆栈(用于在调用函数时持有局部变量并维护状态的内存区域)。每个 Java 线程都需要堆栈空间来运行。根据实现的不同,Java 线程可以分为本机线程和 Java 堆栈。除了堆栈空间,每个线程还需要为线程本地存储(thread-local storage)和内部数据结构提供一些本机内存。
堆栈大小因 Java 实现和架构的不同而不同。一些实现支持为 Java 线程指定堆栈大小,其范围通常在 256KB 到 756KB 之间。
尽管每个线程使用的内存量非常小,但对于拥有数百个线程的应用程序来说,线程堆栈的总内存使用量可能非常大。如果运行的应用程序的线程数量比可用于处理它们的处理器数量多,效率通常很低,并且可能导致糟糕的性能和更高的内存占用。

本机内存耗尽会发生什么?
Java 运行时善于以不同的方式来处理 Java 堆的耗尽与本机堆的耗尽,但这两种情形具有类似的症状。当 Java 堆耗尽时,Java 应用程序很难正常运行,因为 Java 应用程序必须通过分配对象来完成工作。只要 Java 堆被填满,就会出现糟糕的 GC 性能并抛出表示 Java 堆被填满的 OutOfMemoryError。
相反,一旦 Java 运行时开始运行并且应用程序处于稳定状态,它可以在本机堆完全耗尽之后继续正常运行。不一定会发生奇怪的行为,因为需要分配本机内存的操作比需要分配 Java 堆的操作少得多。尽管需要本机内存的操作因 JVM 实现不同而异,但也有一些操作很常见:启动线程、加载类以及执行某种类型的网络和文件 I/O。
本机内存不足行为与 Java 堆内存不足行为也不太一样,因为无法对本机堆分配进行单点控制。尽管所有 Java 堆分配都在 Java 内存管理系统控制之下,但任何本机代码(无论其位于 JVM、Java 类库还是应用程序代码中)都可能执行本机内存分配,而且会失败。尝试进行分配的代码然后会处理这种情况,无论设计人员的意图是什么:它可能通过 JNI 接口抛出一个 OutOfMemoryError,在屏幕上输出一条消息,发生无提示失败并在稍后再试一次,或者执行其他操作。
缺乏可预测行为意味着无法确定本机内存是否耗尽。相反,您需要使用来自操作系统和 Java 运行时的数据执行诊断。


jvm内存映像分析   好东西

一个优秀的Java程序员必须了解GC机制   一个优秀的Java程序员必须了解GC机制 原文

1.最基本的建议就是尽早释放无用对象的引用。 
2.尽量少用finalize函数。finalize函数是Java提供给程序员一个释放对象或资源的机会。但是,它会加大GC的工作量,因此尽量少采用finalize方式回收资源。 
3.注意集合数据类型,包括数组,树,图,链表等数据结构,这些数据结构对GC来说,回收更为复杂。另外,注意一些全局的变量,以及一些静态变量。这些变量往往容易引起悬挂对象(dangling reference),造成内存浪费。 
4.当程序有一定的等待时间,程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。使用增量式GC可以缩短Java程序的暂停时间。

Java中三个引用类SoftReference 、 WeakReference 和 PhantomReference的区别

理解StrongReference,SoftReference, WeakReference的区别

StrongReference 是 Java 的默认引用实现,  它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收
WeakReference, 顾名思义,  是一个弱引用,  当所引用的对象在 JVM 内不再有强引用时, GC 后 weak reference 将会被自动回收
SoftReference 与 WeakReference 的特性基本一致, 最大的区别在于 SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存应用

虚引用主要用来跟踪对象被垃圾回收器回收的活动。

理解 Java 的 GC 与 幽灵引用    Java 中一共有 4 种类型的引用 : StrongReference、 SoftReference、 WeakReference 以及 PhantomReference (传说中的幽灵引用)

java中的4种reference的差别和使用场景(含理论、代码和执行结果)

JVM调优:选择合适的GC collector (一)

HotSpot VM GC 的种类

Java GC 调试手记

GC学习笔记 总结很完整

JVM 垃圾回收算法  【图文非常好】

1.标记—清除算法(Mark-Sweep)
标记—清除算法包括两个阶段:“标记”和“清除”。在标记阶段,确定所有要回收的对象,并做标记。清除阶段紧随标记阶段,将标记阶段确定不可用的对象清除。
2.复制算法(Copying)
复制算法是把内存分成大小相等的两块,每次使用其中一块,当垃圾回收的时候,把存活的对象复制到另一块上,然后把这块内存整个清理掉。
3.标记—整理算法(Mark-Compact)
标记—整理算法和标记—清除算法一样,但是标记—整理算法不是把存活对象复制到另一块内存,而是把存活对象往内存的一端移动,然后直接回收边界以外的内存。
4.分代收集(Generational Collection)
分代收集是根据对象的存活时间把内存分为新生代和老年代,根据个代对象的存活特点,每个代采用不同的垃圾回收算法。新生代采用标记—复制算法,老年代采用标记—整理算法。

线程TLAB区域的深入剖析

(1) 堆是JVM中所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的
(2) Hotspot JVM为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行的情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本是一样高效的,但如果对象过大的话则仍然是直接使用堆空间分配
(3) TLAB仅作用于新生代的Eden Space,因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效。
(4) 所有新创建的Object 都将会存储在新生代Yong Generation中。如果Young Generation的数据在一次或多次GC后存活下来,那么将被转移到OldGeneration。新的Object总是创建在Eden Space。

JVM介绍  【非常全面,图文】

浅析Java虚拟机结构与机制 【全面】面向GC的Java编程

对象都是在堆上分配的吗?

典型的对象不再堆上分配的情况有两种:TLAB和栈上分配。

编写内存效率的java代码-面向GC 【阿里沐剑】

GC最喜欢这种小而短命的对象。让对象的生命周期尽可能短,例如在方法体内创建,使其能尽快地在YoungGC中被回收,不会晋升(romote)到年老代(Old Generation)。
小对象的分配,会优先在线程私有的 TLAB 中分配,TLAB中创建的对象,不存在锁甚至是CAS的开销。TLAB占用的空间在Eden Generation。
当对象比较大,TLAB的空间不足以放下,而JVM又认为当前线程占用的TLAB剩余空间还足够时,就会直接在Eden Generation上分配,此时是存在并发竞争的,所以会有CAS的开销,但也还好。
当对象大到Eden Generation放不下时,JVM只能尝试去Old Generation分配,这种情况需要尽可能避免,因为一旦在Old Generation分配,这个对象就只能被Old Generation的GC或是FullGC回收了。
GC算法在扫描存活对象时通常需要从ROOT节点开始,扫描所有存活对象的引用,构建出对象图。
不可变对象对GC的优化,主要体现在Old Generation中。
Hotspot JVM为了提高YoungGC的性能,避免每次YoungGC都扫描Old Generation中的对象引用,采用了卡表(Card Table) 的方式。
在一个非常大的方法体内,对一个较大的对象,将其引用置为null,某种程度上可以帮助GC。大部分情况下,这种行为都没有任何好处。
System.gc()在JVM启动参数中如果允许显式GC,则会触发FullGC。
Never use Thread.yield()。
Never use System.gc()。除非你真的需要回收Native Memory。
由于Native Memory只能通过FullGC(或是CMS GC)回收,所以除非你非常清楚这时真的有必要,否则不要轻易调用System.gc(),且行且珍惜。
另外为了防止某些框架中的System.gc调用(例如NIO框架、Java RMI),建议在启动参数中加上-XX:+DisableExplicitGC来禁用显式GC。
这个参数有个巨大的坑,如果你禁用了System.gc(),那么上面的3种场景下的内存就无法回收,可能造成OOM,如果你使用了CMS GC,那么可以用这个参数替代:-XX:+ExplicitGCInvokesConcurrent。
如果对象很小,那么分配的开销本来就小,对象池只会增加代码复杂度。
如果对象比较大,那么晋升到Old Generation后,对GC的压力就更大了。
从线程安全的角度考虑,通常池都是会被并发访问的,那么你就需要处理好同步的问题,这又是一个大坑,并且同步带来的开销,未必比你重新创建一个对象小。
对于对象池,唯一合适的场景就是当池中的每个对象的创建开销很大时,缓存复用才有意义,例如每次new都会创建一个连接,或是依赖一次RPC。
即使你真的需要实现一个对象池,也请使用成熟的开源框架,例如Apache Commons Pool。
另外,使用JDK的ThreadPoolExecutor作为线程池,不要重复造轮子,除非当你看过AQS的源码后认为你可以写得比Doug Lea更好。
如果可以在方法内声明的局部变量,就不要声明为实例变量。
除非你的对象是单例的或不变的,否则尽可能少地声明static变量。

成为JavaGC专家Part I — 深入浅出Java垃圾回收机制【画图最好】

绝大多数刚刚被创建的对象会存放在伊甸园空间。
在伊甸园空间执行了第一次GC之后,存活的对象被移动到其中一个幸存者空间。
此后,在伊甸园空间执行GC之后,存活的对象会被堆积在同一个幸存者空间。
当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。
在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。

HotSpot虚拟机使用了两种技术来加快内存分配。他们分别是是”bump-the-pointer“和“TLABs(Thread-Local Allocation Buffers)”。
Bump-the-pointer技术跟踪在伊甸园空间创建的最后一个对象。这个对象会被放在伊甸园空间的顶部。如果之后再需要创建对象,只需要检查伊甸园空间是否有足够的剩余空间。如果有足够的空间,对象就会被创建在伊甸园空间,并且被放置在顶部。这样以来,每次创建新的对象时,只需要检查最后被创建的对象。这将极大地加快内存分配速度。但是,如果我们在多线程的情况下,事情将截然不同。如果想要以线程安全的方式以多线程在伊甸园空间存储对象,不可避免的需要加锁,而这将极大地的影响性能。
TLABs 是HotSpot虚拟机针对这一问题的解决方案。
该方案为每一个线程在伊甸园空间分配一块独享的空间,这样每个线程只访问他们自己的TLAB空间,再与bump-the-pointer技术结合可以在不加锁的情况下分配内存。

成为JavaGC专家Part II — 如何监控Java垃圾回收机制【监控分析】

JVM性能优化, Part 1 ―― JVM简介

JVM性能优化, Part 2 ―― 编译器

JVM性能优化, Part 3 垃圾回收

JVM 性能优化, Part 4: C4 垃圾回收

JVM性能优化, Part 5:Java的伸缩性

JVM并发机制的探讨——内存模型、内存可见性和指令重排序

深入理解JDBC的超时设置

Java编译时与运行时

Java Web Services问题集锦

深入理解JVM内幕:从基本结构到Java 7新特性

Java对象内存结构

如何增强JAVA的I/O性能

JVM垃圾回收机制

深入Java虚拟机之虚拟机体系结构

高手详细介绍JVM是什么?

什么是内存泄漏

Java内存泄露与WeakHashMap

主要有两种情况导致内存泄露:
1、如果Map本省有强引用存在的话,Map中对象即时不被JVM中的任何地方应用到,也不会被回收。
2、如果没有适当的管理,这个Map容器很容易失控,不断的增长。
要避免上面的两种情况,可以在对象不在使用的时候,将它从Map中移除。这就需要容易管理者构造一个清理的函数给对象调用者使用,或者使用一个监听器模式。
然而,这可能不适合某些特定的场景,比如交互式的扩展API。添加这样的函数会使得使用者的API变得更加复杂,增加类之间的耦合度,不好。
一个更简洁当实用的方法是使用一个Map的Key作为ID来标记缓存对象,这时Map不再需要GC来回收对象,而是使用编码逻辑,定期对容器进行检查,对Map进行清理,清除不需要的对象,保持Map容器的容量。
WeakashMap提供一个更优雅的方法解决这个问题。使用WaekHashMap实例化Map。当使用者不再有对象引用的时候,WeakHashMap将自动被移除对应Key值的对象。
正如Java API中对WeakHashMap的描述—-这个容器将不再保护key,不防止对应的key被GC回收。

Java垃圾回收(GC)精华 分代图画的好

深入理解JVM内幕:从基本结构到Java 7新特性

JVM详解 Java虚拟机原理与优化[非常好]

深入JVM [非常好]

深入Java核心 Java内存分配原理精讲

深入Java底层:内存屏障与JVM并发详解

java中Class对象详解

JVM如何判断类相同

JVM系列一:JVM内存组成及分配

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。

JVM系列二:GC策略&内存申请、对象衰老

JVM系列三:JVM参数设置、分析

JVM参数调优,无停滞实践 

1:建议用64位操作系统,Linux下64位的jdk比32位jdk要慢一些,但是吃得内存更多,吞吐量更大。
2:XMX和XMS设置一样大,MaxPermSize和MinPermSize设置一样大,这样可以减轻伸缩堆大小带来的压力。
3:调试的时候设置一些打印参数,如-XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log,这样可以从gc.log里看出一些端倪出来。
4:系统停顿的时候可能是GC的问题也可能是程序的问题,多用jmap和jstack查看,或者killall -3 java,然后查看java控制台日志,能看出很多问题。有一次,网站突然很慢,jstack一看,原来是自己写的URLConnection连接太多没有释放,改一下程序就OK了。
5:仔细了解自己的应用,如果用了缓存,那么年老代应该大一些,缓存的HashMap不应该无限制长,建议采用LRU算法的Map做缓存,LRUMap的最大长度也要根据实际情况设定。
6:垃圾回收时promotion failed是个很头痛的问题,一般可能是两种原因产生,第一个原因是救助空间不够,救助空间里的对象还不应该被移动到年老代,但年轻代又有很多对象需要放入救助空间;第二个原因是年老代没有足够的空间接纳来自年轻代的对象;这两种情况都会转向Full GC,网站停顿时间较长。第一个原因我的最终解决办法是去掉救助空间,设置-XX:SurvivorRatio=65536 -XX:MaxTenuringThreshold=0即可,第二个原因我的解决办法是设置CMSInitiatingOccupancyFraction为某个值(假设70),这样年老代空间到70%时就开始执行CMS,年老代有足够的空间接纳来自年轻代的对象。
7:不管怎样,永久代还是会逐渐变满,所以隔三差五重起java服务器是必要的,我每天都自动重起。
8:采用并发回收时,年轻代小一点,年老代要大,因为年老大用的是并发回收,即使时间长点也不会影响其他程序继续运行,网站不会停顿。
9:因为没有用到救助空间,所以年老代容易满,CMS执行会比较频繁。我改善了一下,还是用救助空间,但是把救助空间加大,这样也不会有promotion failed。

Java字节码浅析(—)
Java字节码浅析(二)

面向GC的Java编程

JVM 实用参数-5 新生代垃圾回收

详细介绍Java的内存管理与内存泄露

JVM的垃圾回收机制详解和调优

走进JVM,浅水也能捉鱼!

浅析JVM内存结构和6大区域

你必须知道的5个JVM命令行标志

JVM中的Hello World

JVM内存模型及垃圾收集策略解析

JVM调优总结(三)-基本垃圾回收算法

JVM调优总结(五)-分代垃圾回收详述1

JVM调优总结(六)-分代垃圾回收详述2

JVM调优总结(十)-调优方法

Java性能优化[3]:垃圾回收(GC)

JVM GC调优一则--增大Eden Space提高性能

《Java虚拟机原理图解》 1.1、class文件基本组织结构【写的极好很完整】

《Java虚拟机原理图解》4.JVM机器指令集 【写的极好很完整】

《Java虚拟机原理图解》5. JVM类加载器机制与类加载过程 【写的极好很完整】

--------------------------------

JVM参数

JVM1.6 GC详解

1.概览监视gc。
   jmap -heap [pid] 查看内存分布
   jstat -gcutil [pid] 1000 每隔1s输出java进程的gc情况
2.详细监视gc。
   在jvm启动参数,加入-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:./gc.log。

jdk分析工具:jmap和jhat

jhat命令

虚拟机故障处理工具

JDK中的bin目录下有很多工具,这些工具可以用来检测虚拟机运行情况以及cpu,内存,线程等的监控,比如jps、jstat、jinfo、jmap、jhat、jstatck等。

Java Class文件详解 【写的极好】

使用WinHex查看Sub类的.class文件。

初识JVM byte code

JVM是一个基于栈(stack-based)的虚拟机。
基于栈的虚拟机其操作数和指令运算的中间结果全部都在一个虚拟栈中,与之对应的是基于寄存器(register-based)的虚拟机,其操作数和指令运算结果会存放在若干个寄存器(也就是存储单元)里。x86机器就可以理解为基于寄存器的机器。

byte code其实和x86汇编代码本质一样,无非是对应机器制定的一堆指令,这里可以举例说明下两类虚拟机的不同:

# stack-based 
push 1       # 压立即数1到栈顶
push 2       # 压立即数2到栈顶
add          # 弹出栈顶2个数相加,将结果3压到栈顶

# register-based
mov ax, 1    # 写立即数到寄存器ax
add ax, 2    # 取ax中的值1与立即数2进行相加,存放结果到ax

---------------------------------------

性能分析工具

http://visualvm.java.net/

Java 性能分析工具

全功能的Java剖析工具(profiler)

常用Java Profiling工具的分析与比较

tomcat 产生heapdump文件配置

Yourkit Java Profiler 使用说明

性能分析软件之yourkit入门介绍

利用JProfiler对应用服务器内存泄漏问题诊断

Java几款性能分析工具的对比


https://www.yourkit.com/

Yourkit Java Profiler 使用说明

Yourkit Eclipse 3.5 plugin installation
Yourkit 使用说明

性能分析软件之yourkit入门介绍


BTrace使用总结

动态跟踪Java代码的执行状况工具--BTrace

jstat的使用方法 -- 分析JVM的使用情况


=============【Java基础】==============

java中静态代码块的用法 static用法详解

java 静态代码块 静态方法区别
一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的. 静态方法在类加载的时候 就已经加载 可以用类名直接调用
比如main方法就必须是静态的 这是程序入口
两者的区别就是:静态代码块是自动执行的;
静态方法是被调用的时候才执行的.

对象的初始化顺序:
首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,
当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;
父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。
总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。
注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。

利用JDB附加调试JAVA程序

HashMap实现原理分析

JAVA学习笔记 -- Vector, ArrayList, Array

Vector这个类是thread safe的。就是说,多线程同时调用同一个Vector的方法不会造成数据的混乱。而ArrayList不是thread safe。所以,如果是多线程的程序,多使用Vector,这样不需要自己维护concurrency。
数据的增长模式不一样。无论是Vector还是ArrayList,内部都是用一个Array来实现的,这就意味着,一旦数据越来越多超过了原来Array的容量的时候,Vector和ArrayList都需要扩充Array来满足新的数据。Vector每次扩充的时候都增长一倍,就是说新的Array的size是旧的Array的size的2倍。而ArrayList每次扩充,它的Array的size只增加50%.
最后,如果程序对于性能要求很高的话,Vector和ArrayList最好哪个都别用,而使用原始的Array。

JAVA学习笔记 -- ”诡异“的List和Array转换

asList()这个函数返回的不是一个”完整的“List对象,而是一个视图(View)。这意味着如果我们改变array中的元素,那么list中的元素也会相应的改变。实际上,array和list指向的是同一组数据。
但是,toArray()这个函数又不存在这个问题。toArray()返回的是一个”safe“的数组。意思就是toArray()会将List中的数据通过值传递的方式拷贝到新的数组中,List中的数据和新创建的数组中的数据不存在引用。如果改变list中的元素,不会影响到array中的数据。
很有趣吧,看上去是一个双向的转换,但其实asList()和toArray()在语义上有着很大的差别。

不简单的JAVA内部类

有了内部类事件驱动模式就非常的容易实现,内部类最大的好处就是它能够达到和多重继承一样的效果。

WeakHashMap 用法和原理

在《Effective Java》一书中第六条,消除陈旧对象时,提到了weakHashMap,即在我们使用短时间内就过期的缓存时最好使用weakHashMap,它包含了一个自动调用的方法expungeStaleEntries,这样就会在值被引用后直接执行这个隐含的方法,将不用的键清除掉。
注意:WeakHashMap并不是你啥也干他就能自动释放内部不用的对象的,而是在你访问它的内容的时候释放内部不用的对象。你只put了没有get过,这个值是永远都存在的。

由于WeakHashMap是在有操作的情况下才会去执行expungeStaleEntries(),将entry中对value的引用释放。

WeakHashMap理解

如何创建不可变(Immutable)的Java类或对象

Java替代C语言的可能性

jdk7新特性

java servlet实例

throw与throws区别

Java基本开发环境搭建

深入理解Java HelloWorld

Servlet 3特性:异步Servlet

Java反射教程

Java Beans序列化缓存  

对象序列化为何要定义serialVersionUID的来龙去脉【很好】

动态绑定 vs 静态绑定

探究内存泄露—Part1—编写泄露代码  探究内存泄露—Part2—分析问题

如何写一个不可变类?  为什么String类是不可变的?

深入理解Java中的final关键字

equals与”==”的区别

clone方法是如何工作的

什么是静态(static)?什么是静态方法,静态变量,静态块和静态类?

Java字符串问题Top10

java中final的意义

java中静态代码块的用法 static用法详解

HashMap和Hashtable的区别  HashMap的工作原理  HashMap和Hashtable的区别

Java遍历Map的两种实现方法

类在什么时候加载和初始化

Eclipse的调试功能的10个小窍门

对比Java.nio 和 Java.io
NIO新功能Top 10

Java NIO原理和使用

Log4j 2 介绍&
Log4j 2.x架构

有效处理Java异常三原则

Java集合框架问题集锦

浅谈WebLogic和Tomcat

Java 集合系列目录(Category)  [很好]

java中length,length(),size()区别

让你明白response.sendRedirect()与request.getRequestDispatcher().forward()区别

response.sendRedirect和request.getRequestDispatcher().forward什么时候用哪个

请说明Request和Session的生命周期

request和session的生命周期

转发和重定向的区别

java 重定向和转发的区别

ArrayList的使用方法

java enum(枚举)使用详解 + 总结

Java抓取网页数据(原网页+Javascript返回数据)

request.getParameterValues与request.getParameter的区别  

request.getParameterValues(String   name)是获得如checkbox类(名字相同,但值有多个)的数据。   接收数组变量 ,如checkobx类型    
request.getParameter(String   name)是获得相应名的数据,如果有重复的名,则返回第一个的值 . 接收一般变量 ,如text类型

Java中@Override的作用

@Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 
1、可以当注释用,方便阅读;
2、编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错。例如,你如果没写@Override,而你下面的方法名又写错了,这时你的编译器是可以编译通过的,因为编译器以为这个方法是你的子类中自己增加的方法。

如何取得wap和web用户的真实IP  [很好]

表现层、持久层、业务层    持久层概述

浅谈序列化与反序列化的理解

Java序列化机制和原理

java 字节流与字符流的区别  [很好]

ClassNotFoundException和NoClassDefFoundError的区别

Integer类介绍

Integer的自动拆装箱的陷阱(整型数-128到127的值比较问题)

Java中的java.math.BigDecimal的使用

Set 不重复实现原理

session和cookie的关系

Java 单例模式详解

java面试题及答案(基础题122道,代码题19道)

Java运行时异常与一般异常以及错误的异同 [很好]

Servlet激活器和缺省Servlet    Servlet激活器

理解java.util包--容器相关

java当中float以及double数据类型的掌握

在《Effective Java》这本书中也提到这个原则: float和double只能用来做科学计算或者是工程计算; 在商业计算中我们要用java.math.BigDecimal。

Java的4种代码块  java“块”的研究  javastatic块

非阻塞队列 和 阻塞队列

一次php和java的性能比拼

在相同的硬件下,如果单个jvm不能完全发挥硬件的性能,通过多个jvm的集群可以,而且会超过PHP。

http://www.anarres.org/projects/jperf/ 

一个完美哈希函数(PHF)的java实现,不过没说是否最小的(MPHF)。

对所以key事先已知,key不再变化的静态字典,(M)PHF能节省内存,同时保持或提高查询时间。

Java性能优化[2]:字符串过滤实战

Java新手进阶:细说引用类型

Google Guava Collections 使用介绍

java.util.logging.Logger使用详解

java.util.logging.Logger不是什么新鲜东西了,1.4就有了,可是因为log4j的存在,这个logger一直沉默着,其实在一些测试性的代码中,jdk自带的logger比log4j更方便。


集合类操作优化经验总结

ArrayList 和 Vector 使用了数组实现,ArrayList 没有对任何一个方法提供线程同步,因此不是线程安全的,Vector 中绝大部分方法都做了线程同步,是一种线程安全的实现。
Vector 非常类似于 ArrayList,区别是 Vector 是线程同步的。
由 Vector 创建的 Iterator,虽然和 ArrayList 创建的 Iterator 是同一接口,但是,因为 Vector 是同步的,
当一个 Iterator 被创建而且正在被使用,另一个线程改变了 Vector 的状态(例如,添加或删除了一些元素),这时调用 Iterator 的方法时将抛出 ConcurrentModificationException,因此必须捕获该异常。


由于作为 Key 的对象将通过计算其散列函数来确定与之对应的 Value 的位置,因此任何作为 key 的对象都必须实现 HashCode 和 Equals 方法。
HashCode 和 Equals 方法继承自根类 Object,如果你用自定义的类当作 Key 的话,要相当小心,按照散列函数的定义,如果两个对象相同,即 obj1.equals(obj2)=true,则它们的 HashCode 必须相同,
但如果两个对象不同,则它们的 HashCode 不一定不同,如果两个不同对象的 HashCode 相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的 HashCode() 方法,能加快哈希表的操作。
如果相同的对象有不同的 HashCode,对哈希表的操作会出现意想不到的结果(期待的 Get 方法返回 Null),要避免这种问题,最好同时复写 Equals 方法和 HashCode 方法,而不要只写其中一个。


HashMap 和 Hashtable 类似,不同之处在于 HashMap 是线程非同步的,并且允许 Null,即 Null Value 和 Null Key。
但是将 HashMap 视为 Collection 时(values() 方法可返回 Collection),其迭代子操作时间开销和 HashMap 的容量成比例。
因此,如果迭代操作的性能相当重要的话,不要将 HashMap 的初始化容量设得过高,或者 Load Factor 参数设置过低。


WeakHashMap 是一种改进的 HashMap,它对 Key 实行“弱引用”,如果一个 Key 不再被外部所引用,那么该 Key 可以被 GC 回收。
WeakHashMap 特点是当除了自身有对 Key 的引用外,如果此 Key 没有其他引用,那么此 Map 会自动丢弃该值。
WeakHashMap 主要通过 expungeStaleEntries 这个函数来实现移除其内部不用的条目,从而达到自动释放内存的目的。
基本上只要对 WeakHashMap 的内容进行访问就会调用这个函数,从而达到清除其内部不再为外部引用的条目。
但是如果预先生成了 WeakHashMap,而在 GC 以前又不曾访问该 WeakHashMap, 那不是就不能释放内存了吗?果不其然,WeakHashMap 这个时候并没有自动帮我们释放不用的内存。
总的来说,WeakHashMap 并不是你什么也干它就能自动释放内部不用的对象的,而是在你访问它的内容的时候释放内部不用的对象。
WeakHashMap 实现弱引用,是因为它的 Entry是继承自 WeakReference的。
WeakHashMap 类是线程不同步的,可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap, 每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除。需要注意的是,WeakHashMap 中的值对象由普通的强引用保持。因此应该小心谨慎,确保值对象不会直接或间接地强引用其自身的键,因为这会阻止键的丢弃。注意,值对象可以通过 WeakHashMap 本身间接引用其对应的键,这就是说,某个值对象可能强引用某个其他的键对象,而与该键对象相关联的值对象转而强引用第一个值对象的键。
处理此问题的一种方法是,在插入前将值自身包装在 WeakReferences 中,如:m.put(key, new WeakReference(value)),然后,分别用 get 进行解包,该类所有“collection 视图方法”返回的迭代器均是快速失败的,在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器自身的 Remove 或 Add 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。
注意,我们不能确保迭代器不失败,一般来说,存在不同步的并发修改时,不可能做出任何完全确定的保证。


LinkedList 使用了循环双向链表数据结构,由一系列表项连接而成,一个表项总是包含 3 个部分,元素内容、前驱表项和后驱表项。
当 ArrayList 对容量的需求超过当前数组的大小时,需要进行扩容。扩容过程中,会进行大量的数组复制操作,而数组复制时,最终将调用 System.arraycopy() 方法。LinkedList 由于使用了链表的结构,因此不需要维护容量的大小,然而每次的元素增加都需要新建一个 Entry 对象,并进行更多的赋值操作,在频繁的系统调用下,对性能会产生一定的影响,在不间断地生成新的对象还是占用了一定的资源。而因为数组的连续性,因此总是在尾端增加元素时,只有在空间不足时才产生数组扩容和数组复制。
ArrayList 是基于数组实现的,而数组是一块连续的内存空间,如果在数组的任意位置插入元素,必然导致在该位置后的所有元素需要重新排列,因此其效率较差,尽可能将数据插入到尾部。LinkedList 不会因为插入数据导致性能下降。
ArrayList 的每一次有效的元素删除操作后都要进行数组的重组,并且删除的元素位置越靠前,数组重组时的开销越大,要删除的元素位置越靠后,开销越小。LinkedList 要移除中间的数据需要便利完半个 List。


HashMap 是将 Key 做 Hash 算法,然后将 Hash 值映射到内存地址,直接取得 Key 所对应的数据。在 HashMap 中,底层数据结构使用的是数组,所谓的内存地址即数组的下标索引。HashMap 的高性能需要保证以下几点:
Hash 算法必须是高效的;
Hash 值到内存地址 (数组索引) 的算法是快速的;
根据内存地址 (数组索引) 可以直接取得对应的值。
HashMap 实际上是一个链表的数组。前面已经介绍过,基于 HashMap 的链表方式实现机制,只要 HashCode() 和 Hash() 方法实现得足够好,能够尽可能地减少冲突的产生,那么对 HashMap 的操作几乎等价于对数组的随机访问操作,具有很好的性能。但是,如果 HashCode() 或者 Hash() 方法实现较差,在大量冲突产生的情况下,HashMap 事实上就退化为几个链表,对 HashMap 的操作等价于遍历链表,此时性能很差。
HashMap 的一个功能缺点是它的无序性,被存入到 HashMap 中的元素,在遍历 HashMap 时,其输出是无序的。如果希望元素保持输入的顺序,可以使用 LinkedHashMap 替代。
LinkedHashMap 继承自 HashMap,具有高效性,同时在 HashMap 的基础上,又在内部增加了一个链表,用以存放元素的顺序。
HashMap 通过 hash 算法可以最快速地进行 Put() 和 Get() 操作。TreeMap 则提供了一种完全不同的 Map 实现。从功能上讲,TreeMap 有着比 HashMap 更为强大的功能,它实现了 SortedMap 接口,这意味着它可以对元素进行排序。TreeMap 的性能略微低于 HashMap。如果在开发中需要对元素进行排序,那么使用 HashMap 便无法实现这种功能,使用 TreeMap 的迭代输出将会以元素顺序进行。LinkedHashMap 是基于元素进入集合的顺序或者被访问的先后顺序排序,TreeMap 则是基于元素的固有顺序 (由 Comparator 或者 Comparable 确定)。
LinkedHashMap 是根据元素增加或者访问的先后顺序进行排序,而 TreeMap 则根据元素的 Key 进行排序。

-------------------------JAVA异常--------------------------------------------

消除Java应用中的Exception开销

抛异常最大的消耗在于构造整个异常栈的过程,如果你的栈很深,特别是用了一些框架的话,这个开销基本是不可忽视的,
最大开销的地方在这里,当你去new一个Exception的时候,会调用父类Throwable的构造函数,Throwable的构造函数中会调用native的fillInStackTrace(),这个方法就会构造整个异常栈了。
要优化这个地方,最简单的方案有两种:

1、去掉异常栈构造
2、去掉异常

------------------------------------------

Java泛型

java 泛型详解  [很全面]
Java使用泛型编程提取类名上T类型
JAVA 泛型 - Class
java泛型T.class的获取

----------------------------------------------    

apache commons包

commons.apache.org

apache commons包简介

common-lang工具类

Apache Commons Pool试用小记

Apache Common Pool的使用

Apache Common Pool包括很多已经实现的Pool,常用的Pool有GenericObjectPool,GenericKeyedObjectPool。

Apache Commons-Pool 源码分析

Commons-Pool首先定义了池管理方面的API,并考虑了多线程,多种数据结构,内容不足等情况。
其次它为我们提供一个同时管理多个池的解决方案。
留给使用者,主要就是PoolableObjectFactory与KeyedPoolableObjectFactory。
只要使用者将对象的生成,销毁,验证,激活与钝化做好,做到完善,没有歧义(比如什么样的状态算是激活,什么是钝化后的状态),那剩下的就可以放心的交给Commons-Pool来管理你的池了。
最好的一个例子也算是官方例子吧,就是Commons-DBCP(数据库连接池)。


采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,从而提高整体的性能。然而池化处理本身也要付出代价,因此,并非任何情况下都适合采用对象池化。
Dr. Cliff Click在JavaOne 2003上发表的《Performance Myths Exposed》中,给出了一组其它条件都相同时,使用与不使用对象池化技术的实际性能的比较结果。他的实测结果表明:
 
对于类似Point这样的轻量级对象,进行池化处理后,性能反而下降,因此不宜池化;
对于类似Hashtable这样的中量级对象,进行池化处理后,性能基本不变,一般不必池化(池化会使代码变复杂,增大维护的难度);
对于类似JPanel这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。
 
根据使用方法的不同,实际的情况可能与这一测量结果略有出入。在配置较高的机器和技术较强的虚拟机上,不宜池化的对象的范围可能会更大。不过,对于像网络和数据库连接这类重量级的对象来说,目前还是有池化的必要。
基本上,只在重复生成某种对象的操作成为影响性能的关键因素的时候,才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话,还是不采用对象池化技术,以保持代码的简明,而使用更好的硬件和更棒的虚拟机来提高性能为佳。

---------------------------------------------------------------------

dom4j

dom4j解析和处理xml文档

dom4j学习总结(一)

dom4j学习总结(二)

使用Dom4j解析XML

----------------------听课笔记----------------------------------

方立勋java学习笔记 [经典]

方立勋Java Web听课笔记--Tomcat

方立勋Java Web听课笔记--Servlet

方立勋Java Web听课笔记--Request--Response对象

方立勋Java Web听课笔记--Cookie---Session

方立勋Java Web听课笔记--JSP

方立勋Java Web听课笔记--JavaBean

方立勋Java Web听课笔记--sql增删改查

方立勋Java Web听课笔记--JDBC对MYSQL的应用preparedStatement和Statement的区别

方立勋Java Web听课笔记JDBC--分页、三种连接池DBCP/C3P0/TOMCAT自带的连接池

方立勋Java Web听课笔记JDBC续-可滚动的结果集-批处理-事务-JDBC执行存储过程

方立勋Java Web听课笔记十四日知识点回顾-自动获取主键-resultSet结果集的滚动

方立勋Java Web听课笔记-DBUtils-QueryRunner-ReslutSetHandler-JDBC多表操作

方立勋Java Web听课笔记-文件上传和下载-ServletFileUpload-解决上传中文乱码问题

方立勋Java Web听课笔记-ServletFilter过滤器-FilterChain过滤器链Filter生命周期

方立勋Java Web听课笔记-映射Filter-Decorator(装饰器模式)-利用Filter对数据压缩(GZIP

方立勋Java Web听课笔记-JavaWeb总结

-----------------Java EE容器---------------------------------

四大Java EE容器(Tomcat、JBoss、Resin、Glassfish)之简单比较

深入剖析Tomcat类加载机制

图解Tomcat类加载机制

==============【JAVA并发编程】=================

Java线程

Java 理论与实践: 正确使用 Volatile 变量

Java语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错。

Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。
要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
对变量的写操作不依赖于当前值。
该变量没有包含在具有其他变量的不变式中。

与锁相比,Volatile 变量是一种非常简单但同时又非常脆弱的同步机制,它在某些情况下将提供优于锁的性能和伸缩性。
如果严格遵循 volatile 的使用条件 —— 即变量真正独立于其他变量和自己以前的值 —— 在某些情况下可以使用 volatile 代替 synchronized 来简化代码。然而,使用 volatile 的代码往往比使用锁的代码更加容易出错。

【Java线程】volatile的适用场景

把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility)。
原子性意味着个时刻,只有一个线程能够执行一段代码,这段代码通过一个monitor object保护。从而防止多个线程在更新共享状态时相互冲突。
可见性则更为微妙,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的。 
如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。

 

volatile 变量不能用作线程安全计数器。虽然增量操作(x++)看上去类似一个单独操作,实际上它是一个由(读取-修改-写入)操作序列组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。
实现正确的操作需要使x 的值在操作期间保持不变,而 volatile 变量无法实现这点。(然而,如果只从单个线程写入,那么可以忽略第一个条件。)

volatile的适用场景
模式 #1:状态标志
也许实现 volatile 变量的规范使用仅仅是使用一个布尔状态标志,用于指示发生了一个重要的一次性事件
而如果使用 synchronized 块编写循环要比使用 volatile 状态标志编写麻烦很多。由于 volatile 简化了编码,并且状态标志并不依赖于程序内任何其他状态,因此此处非常适合使用 volatile。
这种类型的状态标记的一个公共特性是:通常只有一种状态转换;shutdownRequested 标志从false 转换为true,然后程序停止。

【Java线程】锁机制:synchronized、Lock、Condition

java synchronized详解

并发编程网 - ifeve.com

深入理解Java:SimpleDateFormat安全的时间格式化

SimpleDateFormat中的日期格式不是同步的。推荐(建议)为每个线程创建独立的格式实例。如果多个线程同时访问一个格式,则它必须保持外部同步。

1.自己写公用类的时候,要对多线程调用情况下的后果在注释里进行明确说明
2.对线程环境下,对每一个共享的可变变量都要注意其线程安全性
3.我们的类和方法在做设计的时候,要尽量设计成无状态的


解决办法
1.需要的时候创建新实例:
2.使用synchronized同步SimpleDateFormat对象
3.使用ThreadLocal
4.抛弃JDK,使用其他类库中的时间格式化类:


1.使用Apache commons 里的FastDateFormat,宣称是既快又线程安全的SimpleDateFormat, 可惜它只能对日期进行format, 不能对日期串进行解析。
2.使用Joda-Time类库来处理时间相关问题


做一个简单的压力测试,方法一最慢,方法三最快,但是就算是最慢的方法一性能也不差,一般系统方法一和方法二就可以满足,所以说在这个点很难成为你系统的瓶颈所在。
从简单的角度来说,建议使用方法一或者方法二,如果在必要的时候,追求那么一点性能提升的话,可以考虑用方法三,用ThreadLocal做缓存。
Joda-Time类库对时间处理方式比较完美,建议使用。

---------------------------------------

Disruptor

Disruptor原理剖析

Java并发框架剖析--Disruptor_51CTO.COM

剖析Disruptor:为什么会这么快?(三)伪共享

剖析Disruptor:为什么会这么快?(一)锁的缺点

剖析Disruptor:为什么会这么快?(二)神奇的缓存行填充

剖析Disruptor:为什么会这么快?(四)揭秘内存屏障

=====================【NIO】================

Netty

Netty简介

本质:JBoss做的一个Jar包
目的:快速开发高性能、高可靠性的网络服务器和客户端程序
优点:提供异步的、事件驱动的网络应用程序框架和工具,统一的API,适用于不同的协议(阻塞和非阻塞)
通俗的说:一个好使的处理Socket的东东

如果没有Netty?
远古:java.NET + java.io
近代:java.nio
其他:Mina,Grizzly

1、都是Trustin Lee的作品,Netty更晚;
2、Mina将内核和一些特性的联系过于紧密,使得用户在不需要这些特性的时候无法脱离,相比下性能会有所下降,Netty解决了这个设计问题;
3、Netty的文档更清晰,很多Mina的特性在Netty里都有;
4、Netty更新周期更短,新版本的发布比较快;
5、它们的架构差别不大,Mina靠apache生存,而Netty靠jboss,和jboss的结合度非常高,Netty有对google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);
6、Netty比Mina使用起来更简单,Netty里你可以自定义的处理upstream events 或/和 downstream events,可以使用decoder和encoder来解码和编码发送内容;
7、Netty和Mina在处理UDP时有一些不同,Netty将UDP无连接的特性暴露出来;而Mina对UDP进行了高级层次的抽象,可以把UDP当成"面向连接"的协议,而要Netty做到这一点比较困难。

----------------------------------------------

mina

Apache Mina(一)

Apache Mina是一个能够帮助用户开发高性能和高伸缩性网络应用程序的框架。它通过Java nio技术基于TCP/IP和UDP/IP协议提供了抽象的、事件驱动的、异步的API。

Apache Mina 入门实例

=================【JavaEE】===============

JCP

Java标准委员会JCP, http://jcp.org/en/home/index

--------------------------

RMI

RMI(远程接口调用)

RMI 英文全称是"Remote Method Invocation",它的中文名称是"远程方法调用",它就
是利用Java 对象序列化的机制实现分布式计算,实现远程类对象的实例化以及调用的方法。
说的更清楚些,就是利用对象序列化来实现远程调用,也就是上面两个概念的结合体,利用
这个方法来调用远程的类的时候,就不需要编写Socket 程序了,也不需要把对象进行序列
化操作,直接调用就行了非常方便。
远程方法调用是一种计算机之间对象互相调用对方函数,启动对方进程的一种机制,使用这
种机制,某一台计算机上的对象在调用另外一台计算机上的方法时,使用的程序语法规则和
在本地机上对象间的方法调用的语法规则一样。

---------------------------------------

POJO

POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创造的简称。
使用POJO名称是为了避免和EJB混淆起来, 而且简称比较直接. 其中有一些属性及其getter setter方法的类,没有业务逻辑,有时可以作为VO(value -object)或dto(Data Transform Object)来使用.当然,如果你有一个简单的运算属性也是可以的,但不允许有业务方法,也不能携带有connection之类的方法。

"We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it's caught on very nicely."--Martin Fowler
我们疑惑为什么人们不喜欢在他们的系统中使用普通的对象,我们得到的结论是——普通的对象缺少一个响亮的名字,因此我们给它们起了一个,并且取得了很好的效果。——Martin Fowler

POJO和javabean的异同

按照Martin Fowler的解释是“Plain Old Java Object”,从字面上翻译为“纯洁老式的java对象”,但大家都使用“简单java对象”来称呼它。POJO的内在含义是指那些没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的java对象。

Java之POJO

Java的开发者被EJB的繁杂搞怕了,大家经过反思,又回归“纯洁老式”的JavaBean,即有无参构造函数,每个字段都有getter和setter的java类。

--------------------------------------

EJB

到底EJB是什么

EJB 就是将那些"类"放到一个服务器上,用C/S 形式的软件客户端对服务器上的"类"进行调用。

EJB到底是什么,真的那么神秘吗 【非常经典】

a.EJB实现原理: 就是把原来放到客户端实现的代码放到服务器端,并依靠RMI进行通信。
b.RMI实现原理 :就是通过Java对象可序列化机制实现分布计算。
c.服务器集群: 就是通过RMI的通信,连接不同功能模块的服务器,以实现一个完整的功能。

EJB 技术基础正是RMI。通过RMI 技术,J2EE
将EJB 组件创建为远程对象,客户端就可以通过网络调用EJB 对象了。

谈一下EJB

目前ejb已经出到了3.x了,然而国内已经几乎没有使用ejb3.x,有的也是ejb2.x,都是老系统遗留,有的是银行项目,有的是erp项目(都是大型项目)。
之前jboss出名就是因为它支持ejb,并且支持得最好,然而现在随着ejb的使用份额下降,这几年jboss在国内的使用份额也下降了,用tomcat和其他开源服务器多了很多。

ejb的替换开源产品太多了:现在业务逻辑,在java上要用框架的有spring,远程调用,有webservice(apache cxf已经做得很好了,而且webservice又是通用标准),mina(一个apache的NIO框架),netty(现在性能最快的NIO框架,来自jboss).而且这些产品都是可移植,社区交流多,出了问题,google就找到了。

------------------------------

JTA

JTA 深度历险 - 原理与实现

JTA入门

关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 

XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接口。XA接口是双向的系统接口,在事务管理器(Transaction Manager)以及一个或多个资源管理器(Resource Manager)之间形成通信桥梁。XA之所以需要引入事务管理器是因为,在分布式系统中,从理论上讲(参考Fischer等的论文),两台机器理论上无法达到一致的状态,需要引入一个单点进行协调。事务管理器控制着全局事务,管理事务生命周期,并协调资源。资源管理器负责控制和管理实际资源(如数据库或JMS队列)。

作为java平台上事务规范JTA(Java Transaction API)也定义了对XA事务的支持,实际上,JTA是基于XA架构上建模的,在JTA 中,事务管理器抽象为javax.transaction.TransactionManager接口,并通过底层事务服务(即JTS)实现。像很多其他的java规范一样,JTA仅仅定义了接口,具体的实现则是由供应商(如J2EE厂商)负责提供。

MySQL事务学习 --> 分布式事务

Innodb存储引擎支持XA事务,通过XA事务可以支持分布式事务的实现。

在MySQL中的分布式事务中,资源管理器就是mysql数据库,事务管理器为连接到mysql服务器的客户端。

当前的java的jta java transaction API可以很好的支持mysql的分布式事务

Mysql技术内幕InnoDB存储引擎——事务&备份&性能调优

mysql使用JTA实例

JTA(Java Transaction API) 为 J2EE 平台提供了分布式事务服务。 
jdk中自带了javax.transaction和javax.transaction.xa 

数据库三种连接PooledConnection,XAConnection,Connection(连接三剑客) 

----------------------------------------

JNDI

Tomcat 6 --- JNDI详解

JNDI(Java Naming and Directory Interface, Java命名和目录接口),说白了,就是通过配置一些xml文件,方便用户直接调用API使用某些通用的资源。
举个简单的例子,如果在tomcat中部署了很多应用,应用都需要使用同一个数据库,如果每个应用都在代码中配置数据库的连接,肯定是很麻烦的。
所以通过JNDI就可以简单的通过 InitialContext 获取到统一配置的资源,简化代码的编写。

JNDI到底是什么,有什么作用

是为了一个最最核心的问题:是为了解耦,是为了开发出更加可维护、可扩展的系统。
在在J2EE容器中配置JNDI参数,定义一个数据源,也就是JDBC引用参数,给这个数据源设置一个名称;然后,在程序中,通过数据源名称引用数据源从而访问后台数据库。 

1、JNDI 提出的目的是为了解耦,是为了开发更加容易维护,容易扩展,容易部署的应用。 
2、JNDI 是一个sun提出的一个规范(类似于jdbc),具体的实现是各个j2ee容器提供商,sun   只是要求,j2ee容器必须有JNDI这样的功能。 
3、JNDI 在j2ee系统中的角色是“交换机”,是J2EE组件在运行时间接地查找其他组件、资源或服务的通用机制。 
4、JNDI 是通过资源的名字来查找的,资源的名字在整个j2ee应用中(j2ee容器中)是唯一的。 

初识JNDI

Java命名和目录接口(Java Naming and Directory Interface ,JNDI)是用于从Java应用程序中访问名称和目录服务的一组API。命名服务即将名称与对象相关联,以便能通过相应名称访问这些对象。而目录服务即其对象具有属性及名称的命名服务。 
命名或目录服务允许您集中管理共享信息的存储,这在网络应用程序中很重要,因为它可以使这类应用程序更加一致和易于管理。例如,可以将打印机配置存储在目录服务中,这样所有与打印机相关的应用程序都能够使用它。

读完这个我懂了JNDI 

java 关于Lookup的用法

JNDI全面总结

Tomcat配置JNDI数据源

JNDI学习总结(一)——JNDI数据源的配置

JNDI学习总结(二)——Tomcat下使用C3P0配置JNDI数据源

--------------------------------------

JMS和ActiveMQ

JMS是一系列的接口及相关语义的集合,通过这些接口和和其中的方法,JMS客户端如何去访问消息系统,完成创建、发送、接收和读取企业消息系统中消息。

深入浅出JMS(一)——JMS简介

JMS简介与ActiveMQ实战

JMS提供了两种消息通信模型:点到点(P2P)模型 和 发布/订阅(Pub/Sub)模型

深入浅出JMS(一)--JMS基本概念

JMS好处:提供消息灵活性,松散耦合,异步性

深入浅出JMS(二)--ActiveMQ简单介绍以及安装

ActiveMQ是由Apache出品的,一款最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,它非常快速,支持多种语言的客户端和协议,而且可以非常容易的嵌入到企业的应用环境中,并有许多高级功能。

什么情况下使用ActiveMQ?
多个项目之间集成 
(1) 跨平台 (2) 多语言 (3) 多项目
降低系统间模块的耦合度,解耦 
(1) 软件扩展性 系统前后端隔离 
(1) 前后端隔离,屏蔽高安全区

深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例 点对点的同步消息模型

深入浅出JMS(四)--Spring和ActiveMQ整合的完整实例  发布订阅模型

队列模型和PUB/SUB模型的区别,Queue只能由一个消费者接收,其他Queue中的成员无法接受到被已消费的信息,而Topic则可以,只要是订阅了Topic的消费者,全部可以获取到生产者发布的信息。
Spring提供了对JMS的支持,ActiveMQ提供了很好的实现。

--------------------------------------

JMX

(对 JVM 和系统的监测,Sun 公司也在其 Java SE 5 版本中,正式提出了 Java 管理扩展(Java Management Extensions,JMX)用来管理检测 Java 程序(同时 JMX 也在 J2EE 1.4 中被发布))

JMX 入门例子

Java SE 6 新特性: JMX 与系统管理

【JMX】1. 什么是JMX、JDK中的JMX实现

JMX是一种JAVA的正式规范,它主要目的是让程序且有被管理的功能

我的理解--关于jmx

JMX整理

JMX学习笔记(四) JMX RMI

----------------------------------------

JPA

Java持久化API

JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。


JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它不囿于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范。
JPA包括以下3方面的技术:
ORM映射元数据
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
API
用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。


http://www.objectdb.com/

JPA入门例子(采用JPA的hibernate实现版本)

ORM 是Object-Relation-Mapping,即对象关系影射技术,是对象持久化的核心。ORM是对JDBC的封装,从而解决了JDBC的各种存在问题。

JPA是目前比较流行的一种ORM技术之一,所以他拥有ORM技术的各种特点,当然他还有自己的一些优势。

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问 API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

JPA规范的主要内容

Entity Identity 实体标识
Accessor of Persistent Fields and Properties 持久化值域和属性的访问器
Persistence Context 持久化上下
Entity Instance's Life Cycle 实例对象生命周期
Entity Relationships 实体关系:JPA定义了one-to-one、one-to-many、many-to-one、many-to-many 4种关系
Inheritance 继承
Optimistic Locking and Concurrency 乐观锁及并发控制:JPA默认应用层将使用乐观锁机制
Query Language 查询语言:类SQL的语法,但是带上了较明显的对象特征
Metadata:详细的元数据声明规范

----------------------------------------

JAX-WS(JWS)

基于XML的JAX-WS规范

真正的轻量级WebService框架——使用JAX-WS(JWS)发布WebService

简单的Jax-WS WebService实现

利用JAX-WS开发Web服务

----------------

JAX-RS

基于REST的JAX-RS规范

RESTEasy入门

RESTEasy是JBoss的开源项目之一,是一个RESTful Web Services框架。

Jersey框架一:Jersey RESTful WebService框架简介

---------------------------------------

JBI

JBI(Java Business Integration)是SUN公司解决SOA的方案,当然JBI没有得到IBM与BEA的承认(IBM与BEA等公司推荐SCA和SDO)。
JBI(Java Business Integration,Java业务集成,Java业务整合)是一种企业服务总线(Enterprise Service Bus,ESB),使我们能够用Java实现面向服务的架构。
JBI目的主要是在于创建一个可以集成各种组件服务的运行环境,当然这也是一种服务总线思想的体现。
目前流行的服务容器有Servlet容器、EJB容器、JMS容器。

SOA标准之----JBI架构思想

JBI是SUN的标准,是SUN对J2EE容器的一种改进,SUN并不想兼容其他语言的组件。
随着SUN公司被收购,SUN之外的几个巨头都力推SCA标准,SUN的JBI标准将名存实亡,难以得到重用。

JBI容器是为弥补现有J2EE容器的不足而出现的。
JBI容器以一种可插拔的方式集成不同类型的服务,而不是通过编写客户端代码来实现服务的集成。
在JBI容器内部,只有一种标准的规格化消息(Normalized Message)。任务服务组件进入JBI环境之前,通过BC转换为规格消息NM。在JBI环境里,所有的服务都不能相互调用,不论是请求还是回答消息,都要先转给NMR,再由NMR分发。JBI运行环境里面的组件(SE、BC)和NMR都是通过NM来进行信息交换的。
JBI容器的组成的三大部分:
a)、绑定组件(BC:Binding Components):专门用来接收各种不同传输协议的请求,原理是JBI实现了各种不同协议的绑定组件,绑定组件可以细分为接收BC和发送BC。接收BC主要负责发送请求和接收响应,发送BC主要用来调用外部的服务。
b)、服务引擎(SE:Service Engines):这类组件只处理JBI容器内部的消息。JBI容器通常在接收到消息后,需要对请求的消息做一些“处理”,然后再调用外部服务的提供者。
c)、JBI的规格化消息路由器(Normalized Message Router):是JBI内部消息系统的核心,所有的组建之间不能交换消息,只能通过NMR来传递。

--------------------------------------

JCA

一步一步教你用JCA(上)

JCA的全称是J2EE Connector Architecture,它定义了一个连接J2EE平台和Enterprise Information Systems(EIS)的标准架构,使得各个EIS能够接入到Application Server当中。

EIS,全称: Enterprise Information System, 是一个虚的概念,用简单明了的话来讲,就是你现有的系统资源。

JCA就是把你的EIS接进你的Application Server,同时让其它的J2EE组件可以访问到你的EIS。

一步一步教你用JCA(下)

-------------------------------------

BPEL

BPEL 语言介绍和应用

BPEL:全称为Business Process Execution Language,即业务流程执行语言,是一种使用XML编写的编程语言。用于自动化业务流程,也曾经被称作WSBPEL和 BPEL4WS。广泛使用于Web服务相关的项目开发中,优点为具有可移植性和有效保护了投资。 
BPEL是一门用于自动化业务流程的形式规约语言。 用XML文档写入BPEL中的流程能在Web 服务之间以标准化的交互方式得到精心组织。这些流程能够在任何一个符合BPEL规范的平台或产品上执行。 所以,通过允许顾客们在各种各样的创作工具和执行平台之间移动这些流程,BPEL使得他们保护了他们在流程自动化上的投资。

---------------------------------------

ESB

ESB全称为Enterprise Service Bus,即企业服务总线。它是传统中间件技术与XML、Web服务等技术结合的产物

BPEL 或 ESB:应该使用哪一个?

ESB 具有四个主要功能:
消息路由,消息转换,协议中介,事件处理。


ESB 的主要优点之一就是处理消息。
如果需求是以数据为中心的,则显然要选择 ESB。
BPEL 的优点
BPEL 引擎的主要优点是能够编排业务流程。如果需求是处理具有复杂逻辑的流程,则 BPEL 是较好的选择。
如果需求是以流程为中心的,则显然要选择 WS-BPEL。

ESB

ESB定义:ESB是一种在松散耦合的服务和应用之间标准的集成方式。
它可以作用于:
面向服务的架构 -分布式的应用由可重用的服务组成
面向消息的架构 - 应用之间通过ESB发送和接受消息
事件驱动的架构 - 应用之间异步地产生和接收消息
ESB就是在SOA架构中实现服务间智能化集成与管理的中介。

esb和eai的区别

EAI的集成方式从本质而言是基于消息的集成,因此EAI的各组成部件,如适配器与hub,都带有消息转换与消息路由的功能,在EAI的运作过程中,单个应用系统只关心其与EAI连接部分消息的输入与输出,不关心具体的业务处理,业务处理都是在应用系统内部完成的。
SOA的集成方式,其本质是对业务功能服务化后根据业务流程进行编排,是真正意义上的基于功能服务的集成。当然在基于SOA的集成中同样包含了基于消息集成的功能。
因此基于SOA的集成方式比EAI的集成方式适用范围更广。
个人观点:无非是在设计接口时,是面向服务和面向消息的区别。关键在于使用者的设计方式。EAI本身又不是不能设计成支持服务的。


ESB应该是在EAI的架构基础上进一步完善、标准化,并且辅以提供更多的best practice给使用者。这样说估计大家更清楚一些,但很多文章非得把两个说成不一样的东西,好像非得把ESB抬高一个层次,说成不一样的东西,这样反倒让人犯糊涂了。

-------------------------------------

OSGI

基于 OSGi 和 Spring 开发 Web 应用

走近Java模块化系统OSGi

OSGI不是一个应用层面的框架,而是设计层面的规范。
OSGI的目的是模块化,就是为了将一个大的应用分解成较小的模块,这些模块物理上就是一个个的jar包,也就是OSGI bundle。OSGI规范就是指导怎么令这些bundle能更好的有高内聚性、有松藕性,能更好地被复用。
OSGI规范定义了一个叫OSGI framework的平台,这个平台是一个运行在JVM上的应用。它负责管理我们上节提到的bundle(也就是一个符合OSGI规范的Jar包)。

OSGi入门教程

创建OSGi Hello World工程

OSGi是什么,可以用通俗的话描述下吗

----------------------------------------

Apache ServiceMix

Apache ServiceMix是一个开源ESB组件,符合JBI规范。其特点是小巧灵活,可以很方便的集成到J2EE容器中,也可以单独作为一个服务器运行。
Apache ServiceMix项目主页: http://servicemix.apache.org/

-------------------------------------------

Apache CXF

Apache CXF 简介

Apache CXF 是一个开源的 Services 框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。

使用 CXF 做 webservice 简单例子

Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构。它允许创建高性能和可扩展的服务,您可以将这样的服务部署在 Tomcat 和基于 Spring 的轻量级容器中。

Apache CXF 框架结构和基本原理

Apache CXF实战之一 Hello World Web Service

基于Apache CXF的Web Service服务端/客户端

-----------------------------------------------

SOA

SOA分析设计过程

SOA的实施流程

1、做调研,分析现有IT系统面临的问题和挑战。
2、明确公司的组织机构(用例中Actor),为的是搞清楚系统使用者、决策者等人员的关系,也为做系统的用例做好前提准备。
3、画所要集成系统的功能模块图,主要是填写表格(主要项有:所属系统、模块功能、使用者、功能描述等),这一部比较粗略,目的是为系统分出几大块来。
4、根据上步的分析,画出系统的用例图(功能模块不要太细了,这里要把握粗粒度),使用工具是RSA。
5、将用例导入到WBM,并进行业务流程建模。业务流程不要画得太细了(千万不能画成程序流程了,或者半程序流程图)。
6、将业务流程导入RSA,分析流程,提取可能的服务,进行服务建模。
7、对可能的服务进行细致分析,抽取服务。
8、画服务的依赖图
9、画服务的组件图
10、描述服务的消息(服务组件的输入和输出消息)
11、就是将分析的形成的东西导入到WID,可以生成组件的部署xml,并进行编码、部署、测试等。


做SOA的分析设计时,应该时刻保持清醒,SOA是为了系统集成,分析过程是为了形成公用的服务组件,有了组件,可以通过ESB自由相互调用,如果有工作流模块,甚至可以随意组合业务。

SOA、ESB、WebService、SCA、BPEL区别与联系【总结不错】

==================【缓存和序列化】====================

Java json

Json:JSON net.sf.json

---------------------------------

protostuff

protostuff 是一个支持各种格式的一个序列化Java类库,包括 JSON、XML、YAML等格式。

http://code.google.com/p/protostuff/

java的序列化lib protostuff

Java序列化框架自测

java内置的序列化方式性能 protostuff

我们这样做Java Profiling

Unity手游之路<二>Java版服务端使用protostuff简化protobuf开发

在Android 开发中使用Protobuf的实践和经验分享

protobuf简介

Protobuf最好的入门教程

开源点评:Protocol Buffers介绍

---------------------------------------------------------

dyuproject

dyuproject 包含一个基于Servlet的REST框架、OpenID 2.0 的RP实现、oauth 1.0a consumer and service provider, json-ioc

---------------------------------------------------------

MessagePack

是一个基于二进制高效的对象序列化Library用于跨语言通信。MessagePack主要用于结构化数据的缓存和存储:

1.存在Memcache中,因为它比json小,可以省下一些内存来,速度也比json快一些.2.存在可以持久化的Key-val存储中。

msgpack

新型序列化类库MessagePack,比JSON更快、更小的格式

--------------------------------------------------------

jedis

Redis的Java客户端 Jedis

Jedis 2.1在线文档API [不错]

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

代理模式原理及实例讲解

代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问。
现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,似乎当事人并不存在,因为他只和代理人通信。而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人。
在软件设计中,使用代理模式的意图也很多,比如因为安全原因需要屏蔽客户端直接访问真实对象,或者在远程调用中需要使用代理类处理远程方法调用的技术细节 (如 RMI),也可能为了提升系统性能,对真实对象进行封装,从而达到延迟加载的目的。

代理模式角色分为 4 种:
主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;
真实主题:真正实现业务逻辑的类;
代理类:用来代理和封装真实主题;
Main:客户端,使用代理类和主题接口完成一些工作。


延迟加载的核心思想是:如果当前并没有使用这个组件,则不需要真正地初始化它,使用一个代理对象替代它的原有的位置,只要在真正需要的时候才对它进行加载。
使用代理模式的延迟加载是非常有意义的,首先,它可以在时间轴上分散系统压力,尤其在系统启动时,不必完成所有的初始化工作,从而加速启动时间;
其次,对很多真实主题而言,在软件启动直到被关闭的整个过程中,可能根本不会被调用,初始化这些数据无疑是一种资源浪费。


动态代理是指在运行时动态生成代理类。即,代理类的字节码将在运行时生成并载入当前代理的 ClassLoader。与静态处理类相比,动态类有诸多好处。首先,不需要为真实主题写一个形式上完全一样的封装类,假如主题接口中的方法很多,为每一个接口写一个代理方法也很麻烦。如果接口有变动,则真实主题和代理类都要修改,不利于系统维护;其次,使用一些动态代理的生成方法甚至可以在运行时制定代理类的执行逻辑,从而大大提升系统的灵活性。
动态代理类使用字节码动态生成加载技术,在运行时生成加载类。生成动态代理类的方法很多,如,JDK 自带的动态处理、CGLIB、Javassist 或者 ASM 库。
JDK 的动态代理使用简单,它内置在 JDK 中,因此不需要引入第三方 Jar 包,但相对功能比较弱。CGLIB 和 Javassist 都是高级的字节码生成库,总体性能比 JDK 自带的动态代理好,而且功能十分强大。
ASM 是低级的字节码生成工具,使用 ASM 已经近乎于在使用 Java bytecode 编程,对开发人员要求最高,当然,也是性能最好的一种动态代理生成工具。
但 ASM 的使用很繁琐,而且性能也没有数量级的提升,与 CGLIB 等高级字节码生成工具相比,ASM 程序的维护性较差,如果不是在对性能有苛刻要求的场合,还是推荐 CGLIB 或者 Javassist。

代理模式有多种应用场合:远程代理,虚拟代理,安全代理,指针引用,延迟加载。

反射和动态代理

Java反射应用

Java 编程的动态性,第 1 部分: 类和类装入

Java中的反射及Bean容器的实现

编程语言中的反射(Refection)指的是可以在程序运行期动态加载一个类。与之相关的是自省(Introspection),这个指的是程序自己可以获取一个类型的描述信息,例如获取一个类的所有接口定义、一个接口的所有形参。当编程语言有了这些语言特性之后,可以在很大程度上解决代码耦合问题,所以在Java的世界里,可以看到很多库/框架使用了反射技术。

类似Spring的Bean容器实现就是大量运用了反射机制。Bean容器维护了一些Bean对象,简单来说就是一些普通对象。Bean容器可以根据配置创建这些对象,创建时如果这些对象依赖了其他对象,Bean容器还会负责将依赖的对象注入到目标对象中,也就是所谓的依赖注入(dependence injection)。放在模块设计中,又衍生出控制反转(IoC, Inverse of Control)概念,用于描述应用程序在使用一个框架时,不是框架来控制/限制应用程序的架构模式,而是由应用程序来控制框架。

类名.class

类名.class是Class对象的句柄,每个被加载的类,在jvm中都会有一个Class对象与之相对应,如果要创建新的对象,直接使用Class对象的局部class.forName就可以了,不需要用new     类名。


在java中,每个class都有一个相应的Class对象,当编写好一个类,编译完成后,在生成的.class文件中,就产生一个class对象,用来表示这个类的类型信息。获得Class实例的三中方式:
1.利用对象调用getClass()方法获取该对象的Class实例
2.使用Class的静态方法forName(),用类的名字获取一个Class实例
3.运用.calss的方式获取Class实例,对基本数据类型的封装类,还可以采用.TYPE来获取对应的基本数据类型的Class实例

类名.class, class.forName(), getClass()区别

1:Class cl=A.class;  
JVM将使用类A的类装载器, 将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象。
2:Class cl=对象引用o.getClass();
返回引用o运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象 。
3:Class.forName("类名");
.装入类A,并做类的初始化
.getClass()是动态的,其余是静态的。
.class和class.forName()只能返回类内field的默认值,getClass可以返回当前对象中field的最新值
Class.forName() 返回的是一个类,.newInstance() 后才创建一个对象,Class.forName()的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的。

http://bbs.csdn.net/topics/360156657

java虚拟机一开始的时候是不加载这个类的所以这个类的一些静态变量之类的董事是不存在的,只有当你第一次使用这个类的时候虚拟机才会加载这个类。在虚拟机当中存在Class这个类,其他的类的的名称加上.class(即类名.class)是这个类的一个对象。当我们需要使用这个类的时候可以用class的函数通过类名.class来加载这个类或者直接通过使用这个类来让虚拟机加载你的类.

深入探讨 Java 类加载器【IBM文档】

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。
一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。
类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。
实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。

虽然在绝大多数情况下,系统默认提供的类加载器实现已经可以满足需求。
但是在某些情况下,您还是需要为应用开发出自己的类加载器。比如您的应用通过网络来传输 Java 类的字节代码,为了保证安全性,这些字节代码经过了加密处理。
这个时候您就需要自己的类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出要在 Java 虚拟机中运行的类来。


OSGi 模块的这种类加载器结构,使得一个类的不同版本可以共存在 Java 虚拟机中,带来了很大的灵活性。
不过它的这种不同,也会给开发人员带来一些麻烦,尤其当模块需要使用第三方提供的库的时候。

利用动态代理的 Java 验证

动态代理是这样一种类,它可以实现在运行时指定的一组接口。对代理类的方法调用,被分配给调用处理程序,而调用处理程序是在代理类生成的时候指定的。
动态代理类有许多应用程序中使用的接口,其中一个可以用统一的方式有效地处理方法前和方法后的调用操作。
因为验证通常是方法前调用操作,所以动态代理为我们提供了针对前面示例所指出的问题的解决方案。 
动态代理类给了我们一种以统一方式方便地处理任何方法上的验证途径,同时把所有的验证逻辑完全与核心业务逻辑分离开。

调用处理程序类是处理所有数据验证逻辑的地方。调用处理程序类还会把方法调用委托到真正的实现类,以便处理核心业务逻辑。

动态代理类确实有一个重要不足:性能。对动态代理类的方法调用,不会像直接调用对象的方法那样好。所以,在应用程序框架中对动态代理的使用,取决于什么对您更重要:更整洁的架构还是更好的性能。在应用程序的许多方面,性能损失可能是值得的,但是在其他方面,性能则有可能是至关重要的。
所以,有一种解决方案,就是在有些地方用动态代理,在其他地方则不用。

return(User)Proxy.newProxyInstance(User.class.getClassLoader(),new Class[] {User.class},new BusinessObjectInvocationHandler(new UserImpl())); 

Java 理论与实践: 用动态代理进行修饰

动态代理工具 是 java.lang.reflect 包的一部分,在 JDK 1.3 版本中添加到 JDK,它允许程序创建 代理对象,代理对象能实现一个或多个已知接口,并用反射代替内置的虚方法分派,编程地分派对接口方法的调用。
这个过程允许实现“截取”方法调用,重新路由它们或者动态地添加功能。本期文章中,Brian Goetz 介绍了几个用于动态代理的应用程序。

Proxy 模式
Proxy 模式中要创建“stub”或“surrogate”对象,它们的目的是接受请求并把请求转发到实际执行工作的其他对象。
远程方法调用(RMI)利用 Proxy 模式,使得在其他 JVM 中执行的对象就像本地对象一样;
企业 JavaBeans (EJB)利用 Proxy 模式添加远程调用、安全性和事务分界;
而 JAX-RPC Web 服务则用 Proxy 模式让远程服务表现得像本地对象一样。
在每一种情况中,潜在的远程对象的行为是由接口定义的,而接口本质上接受多种实现。
调用者(在大多数情况下)不能区分出它们只是持有一个对 stub 而不是实际对象的引用,因为二者实现了相同的接口;
stub 的工作是查找实际的对象、封送参数、把参数发送给实际对象、解除封送返回值、把返回值返回给调用者。代理可以用来提供远程控制(就像在 RMI、EJB 和 JAX-RPC 中那样),
用安全性策略包装对象(EJB)、为昂贵的对象(EJB 实体 Bean)提供惰性装入,或者添加检测工具(例如日志记录)。


在 5.0 以前的 JDK 中,RMI stub(以及它对等的 skeleton)是在编译时由 RMI 编译器(rmic)生成的类,RMI 编译器是 JDK 工具集的一部分。
对于每个远程接口,都会生成一个 stub(代理)类,它代表远程对象,还生成一个 skeleton 对象,它在远程 JVM 中做与 stub 相反的工作 —— 解除封送参数并调用实际的对象。
类似地,用于 Web 服务的 JAX-RPC 工具也为远程 Web 服务生成代理类,从而使远程 Web 服务看起来就像本地对象一样。
不管 stub 类是以源代码还是以字节码生成的,代码生成仍然会向编译过程添加一些额外步骤,而且因为命名相似的类的泛滥,会带来意义模糊的可能性。
另一方面,动态代理机制支持在编译时没有生成 stub 类的情况下,在运行时创建代理对象。


在 JDK 5.0 及以后版本中,RMI 工具使用动态代理代替了生成的 stub,结果 RMI 变得更容易使用。
许多 J2EE 容器也使用动态代理来实现 EJB。EJB 技术严重地依靠使用拦截(interception)来实现安全性和事务分界;
动态代理为接口上调用的所有方法提供了集中的控制流程路径。

动态代理机制的核心是 InvocationHandler 接口,调用句柄的工作是代表动态代理实际执行所请求的方法调用。传递给调用句柄一个 Method 对象(从 java.lang.reflect 包),参数列表则传递给方法;在最简单的情况下,可能仅仅是调用反射性的方法 Method.invoke() 并返回结果

每个代理都有一个与之关联的调用句柄,只要代理的方法被调用时就会调用该句柄。
根据通用的设计原则:接口定义类型、类定义实现,代理对象可以实现一个或多个接口,但是不能实现类。
因为代理类没有可以访问的名称,它们不能有构造函数,所以它们必须由工厂创建

在早期的 JDK 中,反射的性能很差(就像早期 JDK 中几乎其他每件事的性能一样),但是在近 10 年,反射已经变得快多了。
不必进入基准测试构造的主题,我编写了一个简单的、不太科学的测试程序,它循环地把数据填充到 Set,随机地对 Set进行插入、查询和删除元素。
我用三个 Set 实现运行它:一个未经修饰的 HashSet,一个手写的、只是把所有方法转发到底层的 HashSet 的 Set 适配器,还有一个基于代理的、也只是把所有方法转发到底层 HashSet 的 Set 适配器。
每次循环迭代都生成若干随机数,并执行一个或多个 Set 操作。
手写的适配器比起原始的 HashSet 只产生很少百分比的性能负荷(大概是因为 JVM 级有效的内联缓冲和硬件级的分支预测);
代理适配器则明显比原始 HashSet 慢,但是开销要少于两个量级。
我从这个试验得出的结论是:对于大多数情况,代理方式即使对轻量级方法也执行得足够好,而随着被代理的操作变得越来越重量级(例如远程方法调用,或者使用序列化、执行 IO 或者从数据库检索数据的方法),代理开销就会有效地接近于 0。
当然也存在一些代理方式的性能开销无法接受的情况,但是这些通常只是少数情况。

---------------------------------------------

cglib

cglib动态代理介绍(一)

代理为控制要访问的目标对象提供了一种途径。当访问对象时,它引入了一个间接的层。JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理。
JDK的动态代理用起来非常简单,当它有一个限制,就是使用动态代理的对象必须实现一个或多个接口。
如果想代理没有实现接口的继承的类,可以使用CGLIB包。

1>它广泛的被许多AOP的框架使用,例如:Spring AOP和dynaop,为他们提供方法的interception(拦截);
2>hibernate使用CGLIB来代理单端single-ended(多对一和一对一)关联(对集合的延迟抓取,是采用其他机制实现的)

CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM(Java字节码操控框架),来转换字节码并生成新的类。

Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)[转]

Java编译器编译好Java文件之后,产生.class 文件在磁盘中。这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码。JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class对象.
class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的、具体class文件是怎样组织类信息的,可以参考Java虚拟机规范。


由于JVM通过字节码的二进制信息加载类的,那么,如果我们在运行期系统中,遵循Java编译系统组织.class文件的格式和结构,生成相应的二进制数据,然后再把这个二进制数据加载转换成对应的类,这样,就完成了在代码中,动态创建一个类的能力了。


ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。


Javassist是一个开源的分析、编辑和创建Java字节码的类库。

CGLib动态代理原理及实现

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。

Spring AOP 实现原理与 CGLIB 应用

================【SSH框架】===============

Struts

使用Maven创建struts2工程(注解版)

【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)

Web 框架设计与实现 ( 一 ):Maverick

和 Struts 框架一样,Maverick 使用一个统一的控制器 servlet 作为切入点,由 org.infohazard.Maverick.Controller 类实现,定义在 web.xml 文件中,所有的 URL 都映射到 Controller 类上。
当一个 HTTP 请求发送到 Controller 类中时 Controller 从 /WEB-INF/Maverickl.xml 中获得配置,生成 org.infohazard.Maverick.flow.Controller 对象的实例,

http://tapestry.apache.org/download.html

Tapestry5.3使用总结

---------------------------------------------------------

Hibernate

Hibernate使用技巧

Spring Framework Tutorial – Hello World

【SSH进阶之路】Hibernate基本原理(一)

持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。

原来没有使用Hiberante做持久层开发时,存在很多冗余,如:各种JDBC语句,connection的管理,所以出现了Hibernate把JDBC封装了一下,我们不用操作数据,直接操作它就行了。
ORM,即Object-Relational Mapping,它的作用就是在关系型数据库和对象之间做了一个映射。从对象(Object)映射到关系(Relation),再从关系映射到对象。这样,我们在操作数据库的时候,不需要再去和复杂SQL打交道,只要像操作对象一样操作它就可以了(把关系数据库的字段在内存中映射成对象的属性)。

【SSH进阶之路】Hibernate搭建开发环境+简单实例(二) 【很好的例子】

Hibernate 延迟加载剖析与代理模式应用

Hibernate 的延迟加载(lazy load)是一个被广泛使用的技术。这种延迟加载保证了应用只有在需要时才去数据库中抓取相应的记录。
通过延迟加载技术可以避免过多、过早地加载数据表里的数据,从而降低应用的内存开销。Hibernate 的延迟加载本质上就是代理模式的应用,当程序通过 Hibernate 装载一个实体时,默认情况下,Hibernate 并不会立即抓取它的集合属性、关联实体所以对应的记录,而是通过生成一个代理来表示这些集合属性、关联实体,这就是代理模式应用带来的优势。


只是需要访问 ID 为 1 的 Person 实体,并不想访问这个 Person 实体所关联的 Address 对象。此时有两种情况:
如果不延迟加载,Hibernate 就会在加载 Person 实体对应的数据记录时立即抓取它关联的 Address 对象。
如果采用延迟加载,Hibernate 就只加载 Person 实体对应的数据记录。Hibernate 的延迟加载(lazy load)是一个被广泛使用的技术。这种延迟加载保证了应用只有在需要时才去数据库中抓取相应的记录。
通过延迟加载技术可以避免过多、过早地加载数据表里的数据,从而降低应用的内存开销。Hibernate 的延迟加载本质上就是代理模式的应用,当程序通过 Hibernate 装载一个实体时,默认情况下,Hibernate 并不会立即抓取它的集合属性、关联实体所以对应的记录,而是通过生成一个代理来表示这些集合属性、关联实体,这就是代理模式应用带来的优势。

Hibernate 3 深度解析
Hibernate 的对象关系映射
通过数据表反生成的 Java 对象的工具很多,比如 Jboss Tools 的 HibernateTools 等


Hibernate 的事务管理
Hiberante 是对 JDBC 的轻量级封装,Hiberante 本身并不具备事务管理能力,它是将事务的管理委托给底层的 JDBC 或 JTA 来实现事物的管理和调度的。
Hibernate 支持的事务类型两种 JDBC 和 JTA, 那么这两种事务之间又有什么区别呢? 
Hibernate 的 JDBC 事务是基于 JDBC Connection 实现的,它的生命周期是在 Connection 之内的,也就是说 Hibernate 的 JDBC 事务是不能跨 Connection 的。
Hibernate 的 JTA 事务类型是由 JTA 容器来管理的,JTA 容器对当前加入事务的众多 Connection 进行调度,实现其事务性要求,JTA 的事务周期可横跨多个 JDBC Connection 生命周期。


Hibernate 性能调优
Hibernate 3 以前版本在普通情况下持久化对象时会把该对象的属性全都加载进来,即使有些大对象我们用不到。
因为延迟加载属性只能作用在类级别,Hibernate 3 允许我们在属性级别上应用延迟加载功能,这样就可以有选择的加载对象的属性了。
设置也很简单,只需在属性的 get 方法上加入 @Basic(fetch = FetchType.LAZY) 这行代码就可以了
如果使用 hbm 格式来映射文件的话,那么在属性行加入 lazy=true 即可。


我们上面也提到了关于大数据量缓存的问题,提到对于那些不常用的数据要及时清理缓存,我们可以用 session 的 clear 或 evict 方法。

---------------------------------------------------------

Spring

https://github.com/spring-projects/spring-framework

Spring 注解学习手札

Spring三种实例化Bean的方式

Spring2.5依赖注入方式(DI)

使用Maven配置spring

Spring Bean的作用域

Spring中ApplicationContext的三种不同实现

spring每次getBean(),获得的是否是同一个实例

Spring bean的Scope分析

Spring学习--Bean的scope

spring scope="prototype" 学习笔记

Spring ClassPathXmlApplicationContext和FileSystemXmlApplicationContext

掌握Spring中bean的生命周期

spring bean的生命周期

Spring 3.0 注解注入详解

Spring集合注入

Class.forName()用法详解

this.getClass().getClassLoader().getResourceAsStream(fileName)  相对路径  src开始  ./下去

Java的注解机制——Spring自动装配的实现原理

【SSH进阶之路】Spring的IOC逐层深入——为什么要使用IOC[实例讲解](二)

Spring目前最引人注目的地方,就是IOC=Inversion  Of Control(控制反转)或者DI=Dependence  Injection(依赖注入)的设计思想。

传统方式:决定使用哪一个具体实现是由应用程序负责的,在编译阶段就确定了。
Spring方式:调用类只依赖接口,而不依赖具体的实现类,减少了耦合。控制权交给了容器,在运行期才由容器决定将具体的实现动态的“注入”到调用类的对象中。这也是使用IoC的根本原因。

IoC的优缺点  
优点:
1、把对象的创建和依赖关系定义在了XML文件中,我们改变子类的实现变得异常简单。
2、控制反转减轻了对象之间的耦合度,减轻了对象之间的依赖关系,增加了系统的灵活性,可维护性,以及可移植性等等。
缺点:
1、生成对象的方式变复杂了(事实上操作还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。
2、创建对象因为使用了反射技术,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。
总结:IoC使得面向对象的世界更加简单,面向接口编程成为了可能。

【SSH进阶之路】Spring的IOC逐层深入——Spring的IOC原理[通俗解释一下](三)  

原文:Spring的IOC原理[通俗解释一下] 

IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦。

IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。

IOC的别名:依赖注入(DI)
2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

【SSH进阶之路】Spring的AOP逐层深入——AOP的基本原理(六)

AOP(Aspect Oriented Programming),意思是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP基于IoC基础,是对OOP(Object Oriented Programming,面向对象)的延续。同时,AOP实际是GOF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性和可扩展性,AOP可以说也是这种目标的一种实现。
AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging)等。

1、切面(Aspect):对横切性关注点的模块化,其实就是共有功能的实现。如日志切面、权限切面等。
2、连接点(JoinPoint):就是程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出或字段修改等,但Spring只支持
方法级的连接点。
3、通知(Advice):在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包
括"around"、"before”和"after"等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截
器链。
4、切入点(Pointcut):用于定义通知(Advice)应该切入到哪些连接点(JoinPoint)上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。
5、目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象。
6、代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象的功能等于目标对象的核心
业务逻辑功能加上共有功能。代理对象对于使用者而言是透明的,是程序运行过程中的产物。
7、织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译期、类装载期及运行
期,当然不同的发生点有着不同的前提条件。譬如发生在编译期的话,就要求有一个支持这种AOP实现的特殊编译器;发生在类装
载期,就要求有一个支持AOP实现的特殊类装载器;只有发生在运行期,则可直接通过Java语言的反射机制与动态代理机制来动态
实现。

【SSH进阶之路】Spring的AOP逐层深入——采用注解完成AOP(七)

【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)

总结一下 Spring的IOC、DI

Spring源代码解析(一):IOC容器【转载计文柯书籍】

 1. 创建IOC配置文件的抽象资源 
 2. 创建一个BeanFactory 
 3. 把读取配置信息的BeanDefinitionReader,这里是XmlBeanDefinitionReader配置给BeanFactory 
 4. 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成,这样完成整个载入bean定义的过程。我们的IoC容器就建立起来了。

对于普通ioc容器启动到被客户端使用的步骤大致如下: 定义->定位->装载->注册->创建->注入。

Spring技术内幕——深入解析Spring架构与设计原理(一)IOC实现原理

Spring技术内幕——深入解析Spring架构与设计原理(二)AOP

Spring技术内幕——深入解析Spring架构与设计原理(三)数据库的操作实现

Spring技术内幕——深入解析Spring架构与设计原理(四)Web MVC的实现

Spring技术内幕——深入解析Spring架构与设计原理(五)Spring与远端调用

Spring In Action 4(Spring实战第四版)翻译与理解 第一章 付诸行动

《Spring in Action(4th Edition)》阅读笔记

【Spring实战】—— 16 基于JDBC持久化的事务管理【系列】

Smart Framework:轻量级 Java Web 框架 【阿里专家 写的极好】

从MVC到前后端分离

我们输入的是AJAX请求,输出的是JSON数据,市面上有这样的技术来实现这个功能吗?答案是REST。

我们输入的是AJAX请求,输出的是JSON数据,市面上有这样的技术来实现这个功能吗?答案是REST。
如果将浏览器这一端视为前端,而服务器那一端视为后端的话,可以将以上改进后的MVC模式简化为以下前后端分离模式


可见,有了REST服务,前端关注界面展现,后端关注业务逻辑,分工明确,职责清晰。那么,如何使用REST服务将应用程序进行前后端分离呢?


REST本质上是使用URL来访问资源种方式。
REST是一个“无状态”的架构模式,因为在任何时候都可以由客户端发出请求到服务端,最终返回自己想要的数据,当前请求不会受到上次请求的影响。
也就是说,服务端将内部资源发布REST服务,客户端通过URL来访问这些资源,这不就是SOA所提倡的“面向服务”的思想吗?
所以,REST也被人们看做是一种“轻量级”的SOA实现技术,因此在企业级应用与互联网应用中都得到了广泛应用。


REST看起来还是很简单的,实际上我们往往需要提供一个REST框架,让其实现前后端分离架构,让开发人员将精力集中在业务上,而并非那些具体的技术细节。


如何使前端应用通过AJAX跨域访问后端应用呢?这需要使用到CORS技术来实现,这也是目前最好的解决方案了。
[CORS全称为Cross Origin Resource Sharing(跨域资源共享),服务端只需添加相关响应头信息,即可实现客户端发出AJAX跨域请求。]
CORS技术非常简单,易于实现,目前绝大多数浏览器均已支持该技术(IE8浏览器也支持了),服务端可通过任何编程语言来实现,只要能将CORS响应头写入response对象中即可。

-------------------------------------------------------

SpringMVC

【SpringMVC架构】SpringMVC介绍(一)

【SpringMVC架构】SpringMVC入门实例,解析工作原理(二)

基于servlet实现一个web框架

servlet作为一个web规范,其本身就算做一个web开发框架,但是其web action (响应某个URI的实现)的实现都是基于类的,不是很方便,并且3.0之前的版本还必须通过web.xml配置来增加新的action。servlet中有一个filter的功能,可以配置所有URI的功能都经过filter。我们可以基于filter的功能来实现一个简单的web框架。

--------------------------------------------------------

Spring Data

了解 Spring Data JPA

JPA是sun提出的一个对象持久化规范,各JavaEE应用服务器自主选择具体实现,JPA的设计者是Hibernate框架的作者,因此Hibernate作为Jboss服务器中JPA的默认实现,Oracle的Weblogic使用EclipseLink(以前叫TopLink)作为默认的JPA实现,IBM的Websphere和Sun的Glassfish默认使用OpenJPA(Apache的一个开源项目)作为其默认的JPA实现。
JPA的底层实现是一些流行的开源ORM(对象关系映射)框架,因此JPA其实也就是java实体对象和关系型数据库建立起映射关系,通过面向对象编程的思想操作关系型数据库的规范。

Redis实现 spring-redis-data初学习

Spring Data —— 完全统一的API?

Spring Data 作为SpringSource的其中一个父项目, 旨在统一和简化对各类型持久化存储, 而不拘泥于是关系型数据库还是NoSQL 数据存储。

无论是哪种持久化存储, 数据访问对象(或称作为DAO,即Data Access Objects)通常都会提供对单一域对象的CRUD (创建、读取、更新、删除)操作、查询方法、排序和分页方法等。
Spring Data则提供了基于这些层面的统一接口(CrudRepository,PagingAndSortingRepository)以及对持久化存储的实现。
你可能接触过某一种Spring 模型对象——比如JdbcTemplate——来编写访问对象的实现。基于Spring Data的数据访问对象, 我们只需定义和编写一些查询方法的接口(基于不同的持续化存储, 定义有可能稍有不同)。
Spring Data会在运行时间生成正确的实现。
本文比较MongoDB和Neo4j。

Redis入门很简单之八【Spring Data Redis初探】

redis实现 spring-redis-data初学习

java之redis篇(spring-data-redis整合)

征服 Redis + Jedis + Spring (一)—— 配置&常规操作(GET SET DEL)

使用 Spring Data JPA 简化 JPA 开发

开发 Spring Redis 应用程序

-------------------------------------------------------

权限控制

spring security与apache shiro


-------------------------------------------------------

Hessian

小试Hessian实现Webservice

Hessian官网:http://hessian.caucho.com/
Hessian是一个轻量级的remoting on http工具,采用的是Binary RPC协议,所以它很适合于发送二进制数据,同时又具有防火墙穿透能力。Hessian一般是通过Web应用来提供服务,因此非常类似于平时我们用的WebService。只是它不使用SOAP协议,但相比webservice而言更简单、快捷。

Hessian可通过Servlet提供远程服务,需要将匹配某个模式的请求映射到Hessian服务。也可Spring框架整合,通过它的DispatcherServlet可以完成该功能,DispatcherServlet可将匹配模式的请求转发到Hessian服务。Hessian的server端提供一个servlet基类, 用来处理发送的请求,而Hessian的这个远程过程调用,完全使用动态代理来实现的,建议采用面向接口编程,Hessian服务通过接口暴露。

Hessian处理过程示意图:
客户端——>序列化写到输出流——>远程方法(服务器端)——>序列化写到输出流 ——>客户端读取输入流——>输出结果

hessian学习

导出服务接口jar包
最终服务是提供给客户端调用的,客户端必须知道服务的接口信息(包括接口方法中的传输dto定义),所以得将这些java文件导出成jar,提供给调用方。

使用hessian简单使用

Hessian入门(与Spring集成)

Spring整合Hessian

--------------------------------------------------------

iBatis/MyBatits

iBatis简单入门教程

MyBatis学习总结(一)——MyBatis快速入门

【持久化框架】Mybatis与Hibernate的详细对比 【很好】

Mybatis:小巧、方便、高效、简单、直接、半自动化
Hibernate:强大、方便、高效、复杂、间接、全自动化

mybatis学习笔记(1)-对原生jdbc程序中的问题总结 

---------------------------------------------------------

Playframework

Playframework框架学习网站

有别于其他臃肿的企业级 Java 框架,简洁的 Play 框架提供另外一种选择,它关注于开发者的效率和 RESTful 风格的架构。Play 是 敏捷软件开发 的完美伴侣。

Play 框架自动编译 Java 源代码,然后直接热加载到 JVM 中而不需要重启服务器。你可以编辑代码,框架自动重新加载,然后直接就看到修改后的结果,就像在 LAMP 或者 Rails 环境中一样。

Servlet API 或者 Struts 框架,那么你已经看到了一个把 HTTP 协议和 Java API 以及一些奇怪的概念关联起来的抽象体系。Play 和它们想的不同,一个 Web 应用框架应该让你可以完全地直接地访问 HTTP 协议,这是 Play 和其他 Java Web 框架的一个根本性区别。


HTTP 协议,请求/响应模式,REST 架构风格, 内容类型(content-type)协商 ,统一资源标识符(URI) 都是 Play 框架涉及的主要概念。
例如,绑定一个 URI 模式到 Java 调用只需要这样一行:GET    /clients/{id}        Clients.show

---------------------------------------------------------

Ehcache

Ehcache详细解读

Ehcache 是现在最流行的纯Java开源缓存框架。

---------------------------------------------------------

SSHM集成

【持久化框架】SpringMVC+Spring4+Mybatis3集成,开发简单Web项目+源码下载

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

Maven

中心仓库地址http://search.maven.org

http://mvnrepository.com/

maven常见问题问答

maven 教程一 入门

Maven实战(一)安装与配置

Maven实战(二)构建简单Maven项目

Maven实战(三)Eclipse构建Maven项目   [很好]

Maven实战(四)生命周期

Maven实战(五)坐标详解

Maven实战(六)依赖

Maven实战(七)settings.xml相关配置

Maven常用命令

Maven使用

Maven2的配置文件settings.xml

maven 配置篇 之 settings.xml

Maven3实战笔记01环境配置与使用入门

Maven3实战笔记02坐标和依赖--1

Maven3实战笔记02坐标和依赖--2

Maven3实战笔记03Maven仓库

Maven3实战笔记04Maven的生命周期和插件

Maven3实战笔记05仓库依赖解析与插件解析

Maven3实战笔记06聚合

Maven3实战笔记07继承

Maven3实战笔记08Maven反应堆

Maven3实战笔记09Maven的私服-Nexus常用功能

Maven3实战笔记10使用Maven进行测试

Maven3实战笔记13Maven Profile定制化构建

Maven3实战笔记14Maven生成项目站点

Maven3实战笔记16Maven总结

为你的maven2项目配置资源库

Maven3 安装使用(一)

Maven3 安装使用(二)

Maven3 安装使用(三)--搭建公司局域网maven服务器

Windows 下Nexus搭建Maven私服

将 Smart 构件发布到 Maven 中央仓库

==================【跨界边界延迟绑定和元编程】========================

Groovy

精通 Grails: 构建您的第一个 Grails 应用程序

Grails 为您提供 Rails 风格的开发体验,同时以可靠的 Java 技术作为坚强后盾。
Grails 也离不开 Groovy(请参阅 参考资料)。Groovy 是一种动态语言,它在 JVM 上运行,并且与 Java 语言无缝集成。


Groovy 可以大大减少 Java 代码的数量。在 Groovy 中,不再需要为字段编写 getter 和 setter 方法,因为 Groovy 会自动提供它们。
不再需要编写 for Iterator i = list.iterator() 来循环遍历一系列的项;list.each 可以做相同的事情,而且看上去更简洁,表达更清晰。


Groovy 可以无缝地与已有的代码库集成。Groovy 不会替代 Java 语言 — 它只是提供了增强。您可以很快地掌握 Groovy,因为说到底,Groovy 代码就是 Java 代码。
这两种语言是如此兼容,甚至可以将一个 .java 文件重命名为一个 .groovy 文件 — 例如,将 Person.java 改为 Person.groovy — 从而得到一个有效的(可执行的)Groovy 文件(虽然这个 Groovy 文件并没有用到 Groovy 提供的任何语法)。
Groovy 与 Java 语言的深度兼容意味着 Grails 不需要重新创造内部使用的关键技术。相反,您可以以 Groovy 的方式查看熟悉的 Java 库。


运行 Grails 应用程序所需的一切都在一个 ZIP 文件中。所有的依赖库 — 例如 Groovy、Spring 和 Hibernate — 都已经在那里,随时可以使用。

跨越边界: 延迟绑定

用 Java 语言延迟绑定
Spring 等框架的存在主要是为了延迟绑定,它有助于减缓客户机和服务之间的耦合。
面向方面的编程通过提供能够扩展类的功能(甚至可以超出其当前的功能)的服务来实现延迟绑定。
像 Hibernate 这样的框架也可以延迟绑定,通过反射、代理和其他工具在运行时将持久性功能添加到纯粹、普通的 Java 对象(POJO)中。
现在有很多关于如何用 POJO 编程的流行书籍可供开发人员参考,这些书籍大多会使用愈加复杂的技术(比反射还要先进),而这些技术主要是为了打开类并延迟绑定,从而有效地回避了静态类型。
在其他地方,延迟绑定的方法就不那么成功。依赖于 XML 来延迟绑定的部署描述符有很多问题。
对 XML 的过分依赖和我们对语言中的动态行为的强烈渴望有很大关系,因为这些语言常常有点太过静态,绑定得有点太早,并且有点太受限制。

静态类型语言(如 Java™ 语言和 C)可以在编译时把方法调用绑定到其实现中。这项策略让这类语言可以执行更丰富的语法和类型检查。
比起不具有此项编译时检查功能的动态类型语言来说,静态类型语言更加稳定且具有更佳的性能。然而静态类型语言存在一个严重的局限性:前期绑定。
一些动态类型语言(如 Ruby、Smalltalk 和 Self)允许延迟绑定,它们可以实现另一个层次的编程功能。


后期绑定和前期绑定
编程语言能够将对函数(或在面向对象语言中的方法)的声明从其调用中分离出来。
可以声明一个方法并使用单独的语法调用这个方法,但最终系统需要将这两者绑到一起。将调用和实现绑到一起的过程叫做绑定。
前期先绑定到类型再绑定到实现,还是后期先绑定到类型再绑定到实现,这对一门给定语言的编程体验来说有着显著的影响。
大多数面向对象的语言都在后期绑定到实现,从而允许多态性 ,该功能让您能够将许多不同的子类型表示为一种类型。
Java 代码和 C 主要在前期的一个编译的步骤里绑定到一种类型。使用此策略,编译器就有足够的信息可以捕获许多不同类型的 bug,比如说方法参数或返回值之间类型的不兼容。


连续区间
静态或动态只是连续区间中的点。一些语言高度静态。Java 语言比 C 或 C++ 更为动态。连续区间中的每个点都有一套自已的折衷方式。
Java 语言有许多有助于延迟绑定的功能,这些功能都以相对较高的复杂度为代价。
反射、依赖性注入以及 XML 配置都可用于延迟绑定和减少耦合。一直以来,Java 语言都是通过添加功能(如面向方面编程)来使其更为动态的。


Java 语言需要存在用于编译时绑定的方法。其他语言允许打开的类,这些类能够基于开发人员需求进行改变。
如果您曾长久关注框架的发展,就会发现对延迟绑定的需求在日益增长,这种需求导致了 Java 语言中出现了许多很不自然的捆绑,它们使这门语言变得复杂且模糊。

为了理解连续区间中的点,可以看一下反射的情况。
使用 Java 语言,可以在运行时装载类,通过反射找到一个方法,为该方法验证正确的参数设置,然后执行该方法。
要实现这些功能很可能需要编写很多代码行。
但为延迟绑定所做出的这些努力常常会得不偿失,所以大多数 Java 应用程序开发人员不会使用此项技术。


延迟调用
在静态语言中,编译器在编译时直接将调用绑定到实现。动态语言则有些不同。Ruby、Smalltalk 和 Self 依赖于消息传送来延迟绑定。客户机使用消息传送来指定目标对象、消息和参数集。这完全是一个运行机制。所以动态语言有效地添加了一级间接寻址。它们将消息名绑定到一个对象上,而不是从调用绑定到类型再到实现。然后,将该对象绑定到一个名称或标记,并使用该名称或标记在运行时查找相关的实现。它是这样工作的:
客户机向目标对象发送一条消息。
该消息有一个名称和零个或多个参数。
该目标(可以是类或对象)查找是否有与此消息同名的方法。
如果有,目标对象调用该方法。
如果没有,目标对象向父对象发送一条消息。父对象可能是一个超类(Smalltalk)、一个父对象(Self)或一个模块(Ruby)。
如果在任何父对象中都没找到该方法,会调用一个错误捕捉方法。
上述所有步骤都发生在运行时 。这意味着在执行该消息的语句前,既不需要目标方法,也不需要实现。


对类型策略和绑定策略越是深入研究就越会发现:等到运行时再绑定到调用或类型会根本性地改变编程的过程,从而开启一个全新的可能世界。
没错,您会发现这样不那么安全。但您也会发现:重复少了、功能强大了并且在减少代码行的同时有了更大的灵活性。

函数式思维: 函数设计模式,第 2 部分

Groovy 的出色特性之一是提供对元编程的有力支持。我将使用元编程通过 ExpandoMetaClass 将适配器直接构建到类中。
ExpandoMetaClass
动态语言的一个常见特性是开放类:可以重新打开现有的类(您的类或系统类,比如 String 或 Object)以添加、移除或更改方法。开放类在特定领域语言 (DSLs) 中运用颇多,常用于构建流畅接口。Groovy 拥有针对开放类的两个机制:categories 和 ExpandoMetaClass。

函数式思维: 函数设计模式,第 3 部分

Ruby元编程

Ruby中的元编程,是可以在运行时动态的操作语言结构(如类、模块、实例变量等)的技术。你甚至于可以在不用重启的情况下,在运行时直接键入一段新的Ruby代码,并执行他。 
Ruby的元编程,也具有“利用代码来编写代码”的作用。

JavaScript 中的函数式编程实践

在函数式编程语言中,函数是第一类的对象,也就是说,函数 不依赖于任何其他的对象而可以独立存在,而在面向对象的语言中,函数 ( 方法 ) 是依附于对象的,属于对象的一部分。
这一点决定了函数在函数式语言中的一些特别的性质,比如作为传出/传入参数,作为一个普通的变量等。

匿名函数
在函数式编程语言中,函数是可以没有名字的,匿名函数通常表示:“可以完成某件事的一块代码”。
这种表达在很多场合是有用的,因为我们有时需要用函数完成某件事,但是这个函数可能只是临时性的,那就没有理由专门为其生成一个顶层的函数对象。

柯里化
柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

柯里化在 DOM 的回调中非常有用。

高阶函数
高阶函数即为对函数的进一步抽象,事实上,我们在匿名函数小节提到的 map 函数即为一种高阶函数,在很多的函数式编程语言中均有此函数。

map(array, func) 的表达式已经表明,将 func 函数作用于 array 中的每一个元素,最终返回一个新的 array,应该注意的是,map 对 array 和 func 的实现是没有任何预先的假设的,因此称之为“高阶”函数。

闭包及其使用
闭包是一个很有趣的主题,当在一个函数 outter 内部定义另一个函数 inner,而 inner 又引用了 outter 作用域内的变量,在 outter 之外使用 inner 函数,则形成了闭包。

function outter(){ 
  var n = 0; 
  return 
function (){ 
  return n++; 
 } 
 } 


  var o1 = outter(); 
 o1();//n == 0 
 o1();//n == 1 
 o1();//n == 2 
  var o2 = outter(); 
 o2();//n == 0 
 o2();//n == 1
匿名函数 function(){return n++;} 中包含对 outter 的局部变量 n 的引用,因此当 outter 返回时,n 的值被保留 ( 不会被垃圾回收机制回收 ),持续调用 o1(),将会改变 n 的值。
而 o2 的值并不会随着 o1() 被调用而改变,第一次调用 o2 会得到 n==0 的结果,用面向对象的术语来说,就是 o1 和 o2 为不同的 实例,互不干涉。

跨越边界: JavaScript 语言特性

高阶函数: 一个高阶函数可以将函数作为参数,也可以返回一个函数。

动态类型
通过静态类型,编译器可以检查参数和变量的值或针对一个给定操作所允许的返回值。其优势是编译器可以做额外的错误检查。而且静态类型还可以为诸如 IDE 这样的工具提供更多信息,带来其他一些特性,比如更好的代码完成功能。


但静态类型也存在着如下一些劣势:
1.必须提前声明意图,这常常会导致灵活性降低。例如,更改一个 Java 类就会更改类的类型,因而必须重新编译。对比之下,Ruby 允许开放的类,但更改一个 Java 类还是会更改类的类型。
2.要实现相同的功能,必须输入更多的代码。例如,必须用参数形式包括进类型信息,必须用函数形式返回值和所有变量的类型。另外,还必须声明所有变量并显式地转化类型。
3.静态语言的编译-部署周期要比动态语言的部署周期长,尽管一些工具可被用来在某种程度上缓解这一问题。


静态类型更适合用于构建中间件或操作系统的语言中。UI 开发常常需要更高的效率和灵活性,所以更适合采用动态类型。

对象模型
Java 语言是基于类的。当构建应用程序时,也同时构建了可以作为所有对象的模板的新类。然后调用 new 来实例化该模板,创建一个新对象。
而在 JavaScript 中,所创建的是一个原型,此原型是一个实例,可以创建所有未来的对象。

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

Elasticsearch 

使用 Spring、Elasticsearch 及 Logstash 构建企业级数据搜索和分析平台

搜索引擎选择: Elasticsearch与Solr

Lucene只是一个框架,要充分利用它的功能,需要使用JAVA,并且在程序中集成Lucene。需要很多的学习了解,才能明白它是如何运行的,Lucene确实非常复杂。
Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作。
优点:成熟的解决方案,有很多的成功案例。apache 顶级项目,正在持续快速的进步。庞大而活跃的开发社区,大量的开发人员。它只是一个类库,有足够的定制和优化空间:经过简单定制,就可以满足绝大部分常见的需求;经过优化,可以支持 10亿+ 量级的搜索。
缺点:需要额外的开发工作。所有的扩展,分布式,可靠性等都需要自己实现;非实时,从建索引到可以搜索中间有一个时间延迟,而当前的“近实时”(Lucene Near Real Time search)搜索方案的可扩展性有待进一步完善


当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。
随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。
综上所述,Solr的架构不适合实时搜索的应用。


Elasticsearch 与 Solr 的比较总结
二者安装都很简单;
Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。
Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用。

==================【数据库事务】===================

不可重复读和幻读的有什么区别

1) "不可重复读" 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。
那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。
这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。


要避免这种情况,通常可以用 set tran isolation level repeatable read 来设置隔离级别,
这样事务A 在两次读取表T中的数据时,事务B如果企图更改表T中的数据(细节到事务A读取数据)时,就会被阻塞,知道事务A提交! 这样就保证了,事务A两次读取的数据的一致性。


2)幻觉读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。
同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
事务A要两次读取表T的中数据,虽然设置 repeatable read  可以防止事务B对数据进行修改,但是事务B却可以向表T中插入新的数据。如何防止这个问题,我们可以考虑设置最高的事务隔离级别 set tran isolation level serializable。
于是乎,事务B就只能等待事务A的提交,才能想表T中插入新的数据,从而避免了幻读!


隔离级别如果设置成最高,那么势必会带来并发的性能问题。
----------------
邹建总结:
不可重复读的重点是修改:
同样的条件, 你读取过的数据, 再次读取出来发现值不一样了


幻读的重点在于新增或者删除
同样的条件, 第1次和第2次读出来的记录数不一样


当然, 从总的结果来看, 似乎两者都表现为两次读取的结果不一致.
但如果你从控制的角度来看, 两者的区别就比较大
对于不可重复读, 只需要锁住满足条件的记录
对于幻读, 要锁住满足条件及其相近的记录

幻读和不可重复读的区别

你需要明白的脏读,不可重复读,幻读

脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚。

脏读、不可重复读、幻读区别

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

1. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2. 不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。
那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。
这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
3. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 
同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。
那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。


补充 : 基于元数据的 Spring 声明性事务 :
Isolation 属性一共支持五种事务设置,具体介绍如下:
l          DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .
l          READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
l          READ_COMMITTED  会出现不可重复读、幻读问题(锁定正在读取的行)
l          REPEATABLE_READ 会出幻读(锁定所读取的所有行)
l          SERIALIZABLE 保证所有的情况不会发生(锁表)


不可重复读的重点是修改 : 
同一事务,两次读取到的数据不一样。
幻读的重点在于新增或者删除 
同样的条件 ,   第 1 次和第 2 次读出来的记录数不一样


脏读:
强调的是第二个事务读到的不够新。

=================【分布式理论】===================

CAP原理

CAP定理 [wiki]

以两军问题为背景来演绎Basic Paxos【最形象,paxos和两军问题,不是说paxos解决了两军问题,只是借用两军问题的背景来演绎paxos。】

一步一步理解Paxos算法【黑夜路人 画图不错】

Paxos算法细节详解(一)--通过现实世界描述算法【很好】

在最初的第二阶段,议题是先入为主的,谁先占了先机,后面的proposer在第一阶段就会学习到这个议题而修改自己本身的议题,因为这样没职业操守,才能让一致性得到保证,这就是paxos算法的一个过程。原来paxos算法里的角色都是这样的不靠谱,不过没关系,结果靠谱就可以了。该算法就是为了追求结果的一致性。

Paxos在大型系统中常见的应用场景

Paxos是一个分布式选举算法就够了。
1. database replication, log replication等, 如bdb的数据复制就是使用paxos兼容的算法。Paxos最大的用途就是保持多个节点数据的一致性。
2. naming service, 如大型系统内部通常存在多个接口服务相互调用。
3.config配置管理
4.membership用户角色/access control list, 比如在权限设置中,用户一旦设置某项权限比如由管理员变成普通身份,这时应在所有的服务器上所有远程CDN立即生效,否则就会导致不能接受的后果。
5. 号码分配。通常简单的解决方法是用数据库自增ID, 这导致数据库切分困难,或程序生成GUID, 这通常导致ID过长。更优雅的做法是利用paxos算法在多台replicas之间选择一个作为master, 通过master来分配号码。当master发生故障时,再用paxos选择另外一个master。


Yahoo!开源的ZooKeeper [5]是一个开源的类Paxos实现。它的编程接口看起来很像一个可提供强一致性保证的分布式小文件系统。对上面所有的场合都可以适用。但可惜的是,ZooKeeper并不是遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,因此它的理论[6]并未经过完全证明。但由于ZooKeeper在Yahoo!内部已经成功应用在Hbase, Yahoo! Message Broker, Fetch Service of Yahoo! crawler等系统上,因此完全可以放心采用。

如何浅显易懂地解说 Paxos 的算法?

CAP原理与最终一致性

CAP理论以及Eventually Consistent 解析

关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究

两阶段提交协议(two phase commit protocol,2PC)

分布式系统的CAP理论

CA without P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。
但其实分区不是你想不想的问题,而是始终会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA。
CP without A:如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。
很多传统的数据库分布式事务都属于这种模式。
AP wihtout C:要高可用并允许分区,则需放弃一致性。
一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。

分布式系统的BASE理论

BASE是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。

基本可用(Basically Available)
基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。
电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。


软状态( Soft State)
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。
分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。


最终一致性( Eventual Consistency)
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。


ACID和BASE的区别与联系
ACID是传统数据库常用的设计理念,追求强一致性模型。BASE支持的是大型分布式系统,提出通过牺牲强一致性获得高可用性。


ACID和BASE代表了两种截然相反的设计哲学
在分布式系统设计的场景中,系统组件对一致性要求是不同的,因此ACID和BASE又会结合使用。

CAP原理和BASE思想

分布式领域CAP理论,
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容错性) 可靠性

定理:任何分布式系统只可同时满足二点,没法三者兼顾。
忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。

关系数据库的ACID模型拥有 高一致性 + 可用性 很难进行分区:
Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。
Durability. 一旦事务完成,就不能返回。
跨数据库事务:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的,JavaEE中的JTA事务可以支持2PC。因为2PC是反模式,尽量不要使用2PC,使用BASE来回避。

BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性:
Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)
Soft state软状态 状态可以有一段时间不同步,异步。
Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。


简单了解分布式系统

集中式系统用一句话概括就是:一个主机带多个终端。

在《分布式系统概念与设计》一书中,对分布式系统做了如下定义:
分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统
简单来说就是一群独立计算机集合共同对外提供服务,但是对于系统的用户来说,就像是一台计算机在提供服务一样。

分布式系统的一致性探讨

分布式领域CAP理论告诉我们,任何一个分布式系统都无法同时满足Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性) 这三个基本需求。最多只能满足其中两项。 但是,一个分布式系统无论在CAP三者之间如何权衡,都无法彻底放弃一致性(Consistency),如果真的放弃一致性,那么就说明这个系统中的数据根本不可信,数据也就没有意义,那么这个系统也就没有任何价值可言。所以,无论如何,分布式系统的一致性问题都需要重点关注。

有的架构师还说在某些场景中可以牺牲一致性呢?
通常这里说的放弃一致性指的是放弃数据的强一致性。

强一致性
当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。
弱一致性
系统并不保证续进程或者线程的访问都会返回最新的更新过的值,可能保证在某个时间级别之后,可以让数据达到一致性状态。
最终一致性
弱一致性的特定形式。
在没有后续更新的前提下,系统最终返回上一次更新操作的值。
在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。DNS是一个典型的最终一致性系统。

关于分布式事务、两阶段提交协议、三阶提交协议

分布式事务是指会涉及到操作多个数据库的事务。其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。

二阶段提交:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。
两个阶段是指:第一阶段:准备阶段(投票阶段)和第二阶段:提交阶段(执行阶段)。
二阶段提交还是有几个缺点的:
1、同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
2、单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
3、数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
4、二阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

三阶段提交有两个改动点。
1、引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。

相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

无论是二阶段提交还是三阶段提交都无法彻底解决分布式的一致性问题。只有一种一致性算法,那就是Paxos,所有其他一致性算法都是Paxos算法的不完整版。

并行和并发需要不同的工具

NoSQL数据库笔谈

事务和两阶段提交

NoSQL反模式 - 文档数据库篇

数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示

大话Sheepdog 1 – 智能节点管理

大话Sheepdog 2 – 对象缓存

分布式锁服务器

Chubby:面向松散耦合的分布式系统的锁服务   [谷歌原文翻译]

分布式系统领域经典论文翻译集

Bigtable:结构化数据的分布式存储系统

HBase vs Cassandra:我们迁移系统的原因[文章老 但是分布式理论说的还可以]

构建可伸缩,高性能的互联网应用

高性能IO设计的Reactor和Proactor模式

写了一个分布式名字服务JCM  作者另一个博客:http://www.cppblog.com/kevinlynx/

在分布式系统中,某个服务为了提升整体服务能力,通常部署了很多实例。这里我把这些提供相同服务的实例统称为集群(cluster),每个实例称为一个节点(Node)。一个应用可能会使用很多cluster,每次访问一个cluster时,就通过名字服务获取该cluster下一个可用的node。那么,名字服务至少需要包含的功能:


根据cluster名字获取可用的node
对管理的所有cluster下的所有node进行健康度的检测,以保证始终返回可用的node

jcm.server instance是分为leader和follower的,真正的写入操作只有leader进行,follower收到写操作请求时转发给leader。

leader写数据优先更新内存中的数据再写入zookeeper,内存中的数据更新当然是需要加锁互斥的,从而保证数据的正确性。

leader和follower是如何确定角色的?这个很简单,标准的利用zookeeper来进行主从选举的实现。

名字服务在分布式系统中虽然是基础服务,但往往承担了非常重要的角色,数据同步出现错误、节点状态出现瞬时的错误,都可能对整套系统造成较大影响,业务上出现较大故障。所以名字服务的健壮性、可用性非常重要。实现中需要考虑很多异常情况,包括网络不稳定、应用层的错误等。为了提高足够的可用性,一般还会加多层的数据cache,例如subscriber端的本地cache,server端的本地cache,以保证在任何情况下都不会影响应用层的服务。

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

Zookeeper

ZooKeeper Java Example

Distributed Coordination with Zookeeper

ZooKeeper-李建斌[很好很全]

zookeeper学习记录[很好]

分布式服务框架 Zookeeper -- 管理分布式环境中的数据

zookeeper学习记录  [很好]

ZooKeeper系列之二:ZooKeeper数据模型、命名空间以及节点的概念

利用ZooKeeper服务实现分布式系统的配置数据同步

架构设计:远程调用服务架构设计及zookeeper技术详解(上篇)

架构设计:一种远程调用服务的设计构思(zookeeper的一种应用实践)

zookeeper原理与安装

分布式网站架构后续:zookeeper技术浅析

Google利器之Chubby  [非常好懂]

Apache Zookeeper入门1

HBase安装笔记一Zookeeper

ZooKeeper安装与操作实例

大数据处理的基础环境(一)——zookeeper集群环境搭建

zookeeper的集群模式下的安装和配置

zookeeper 集群安装(单点与分布式成功安装)摘录

Zookeeper 的学习与运用



原文链接:http://blog.csdn.net/unix21/article/details/50714930



你可能感兴趣的:(01,-,Java)