paulwong

#

你需要知道的J2EE的25个标准

  1. 你需要精通面向对象分析与设计(OOA/OOD)、涉及模式(GOF,J2EEDP)以及综合模式。你应该了解UML,尤其是class,object,interaction以 及statediagrams。

  2. 你需要学习JAVA语言的基础知识以及它的核心类库(collections,serialization,streams,networking,?multithreading,reflection ,event,handling,NIO,localization,以及其他)。

  3. 你应该了解JVM,classloaders,classreflect,以及垃圾回收的基本工作机制等。你应该有能力反编译一个类文件并且明白一些基本的汇 编指令

  4. 如果你将要写客户端程序,你需要学习WEB的小应用程序(applet),必需掌握GUI设计的思想和方法,以及桌面程序的SWING,AWT,?SWT。 你还应该对UI部件的JAVABEAN组件模式有所了解。JAVABEANS也被应用在JSP中以把业务逻辑从表现层中分离出来。

  5. 你需要学习java数据库技术,并且会使用至少一种persistence/ORM构架,例如Hibernate,JDO,?CocoBase,TopLink,InsideLiberator(国产JDO红工厂软件)或者iBatis。

  6. 你还应该了解对象关系的阻抗失配的含义,以及它是如何影响业务对象的与关系型数据库的交互,和它的运行结果,还 需要掌握不同的数据库产品运用,比如:oracle,mysql,mssqlserver。

  7. 你需要学习Servlets,JSP,以及JSTL(StandardTagLibraries)和可以选择的第三方TagLibraries。

  8. 你需要熟悉主流的网页框架,例如JSF,Struts,Tapestry,Cocoon,WebWork,以及他们下面的涉及模式,如 MVC/MODEL2。

  9. 你需要学习如何使用及管理WEB服务器,例如tomcat,resin,Jrun,并且知道如何在其基础上扩展和维护WEB程序。

  10. 你需要学习分布式对象以及远程API,例如RMI和RMI/IIOP。

  11. 你需要掌握各种流行中间件技术标准和与java结合实现,比如Tuxedo、CROBA,当然也包括javaEE本身。

  12. 你需要学习最少一种的XMLAPI,例如JAXP(JavaAPIforXMLProcessing),JDOM(JavaforXMLDocumentObjectModel),DOM4J,或JAXR (JavaAPIforXMLRegistries)。

  13. 你应该学习如何利用JAVA的API和工具来构建WebService。例如JAX-RPC(JavaAPIforXML/RPC),SAAJ(SOAPwithAttachmentsAPIforJava) ,JAXB(JavaArchitectureforXMLBinding),JAXM(JavaAPIforXMLMessaging),?JAXR(JavaAPIforXMLRegistries),或者JWSDP (JavaWebServicesDeveloperPack)。

  14. 你需要学习一门轻量级应用程序框架,例如Spring,PicoContainer,Avalon,以及它们的IoC/DI风格(setter,constructor, interfaceinjection)。

  15. 你需要熟悉不同的J2EE技术,例如JNDI(JavaNamingandDirectoryInterface),JMS?(JavaMessageService),JTA/JTS (JavaTransactionAPI/JavaTransactionService),JMX?(JavaManagementeXtensions),以及JavaMail。

  16. 你需要学习企业级JavaBeans(EJB)以及它们的不同组件模式:Stateless/StatefulSessionBeans,EntityBeans(包含Bean-ManagedPersistence[BMP]或者Container-ManagedPersistence[CMP]和它的EJB-QL),或者Message-DrivenBeans(MDB)。

  17. 你需要学习如何管理与配置一个J2EE应用程序服务器,如WebLogic,JBoss等,并且利用它的附加服务,例如簇类,连接池以及分布式处理支援。你还需要了解如何在它上面封装和配置应用程序并且能够监控、调整它的性能。

  18. 你需要熟悉面向方面的程序设计以及面向属性的程序设计(这两个都被很容易混淆的缩写为AOP),以及他们的主 流 jAVA 规格和执行。例如 AspectJ和AspectWerkz。

  19. 你需要熟悉对不同有用的API和frame work等来为你服务。例如Log4J(logging/tracing),Quartz?(scheduling),JGroups
    (networkgroupcommunication),JCache(distributedcaching),?Lucene(full-textsearch),JakartaCommons等等。

  20. 你应该熟练掌握一种JAVAIDE例如sunOne,netBeans,IntelliJIDEA或者Eclipse。(有些人更喜欢VI或EMACS来编写文件。 随便你用什么了:

  21. JAVA(精确的说是有些配置)是冗长的,它需要很多的人工代码(例如EJB),所以你需要熟悉代码生成工具,例如XDoclet。

  22. 你需要熟悉一种单元测试体系(JNunit),并且学习不同的生成、部署工具(Ant,Maven)。

  23. 你需要熟悉一些在JAVA开发中经常用到的软件工程过程。例如RUP(RationalUnifiedProcess)andAgilemethodologies。

  24. 你还需要紧跟java发展的步伐,比如现在可以深入的学习webwork2.0

  25. 你必需要对实际项目的开发流程有所了解,至少要有两个有实际应用价值的项目,而不是练习项目!因为现在企业看重的是你有没有实 际的开发经验,真正开发经验的体现就是你做的项目,也就是有实际应用的项目!

posted @ 2011-11-03 20:29 paulwong 阅读(401) | 评论 (0)编辑 收藏

Maven常用Settings.xml

<?xml version="1.0" encoding="UTF-8"?> 
<settings> 
    
<servers> 
        
<server> 
            
<id>tomcat</id> 
            
<username>tomcat</username> 
            
<password>tomcat</password> 
            
<privateKey>${usr.home}/.ssh/id_dsa</privateKey>   
            
<passphrase>some_passphrase</passphrase>   
            
<filePermissions>664</filePermissions>   
            
<directoryPermissions>775</directoryPermissions>   
            
<configuration></configuration>   
        
</server> 
        
<server> 
            
<id>tomcat2</id> 
            
<username>tomcat2</username> 
            
<password>tomcat2</password> 
        
</server> 
    
</servers> 
    
<profiles> 
        
<profile> 
         
<id>default</id> 
           
<activation>   
        
<activeByDefault>false</activeByDefault>   
        
<jdk>1.6.0_24</jdk>   
        
<os>   
          
<name>windows 7</name>   
          
<family>windows</family>   
          
<arch>x86</arch>   
          
<version>6.1</version>   
        
</os>   
        
<property>   
          
<name>mavenVersion</name>   
          
<value>2.2.1</value>   
        
</property>   
        
<file>   
          
<exists>${basedir}/file2.properties</exists>   
          
<missing>${basedir}/file1.properties</missing>   
        
</file>   
      
</activation> 
            
<repositories> 
                
<repository> 
                    
<id>spring-maven-release</id> 
                    
<name>Spring Maven Release Repository</name> 
                    
<url>http://maven.springframework.org/release</url> 
                
</repository> 
                
<repository> 
                    
<id>spring-maven-milestone</id> 
                    
<name>Spring Maven Milestone Repository</name> 
                    
<url>http://maven.springframework.org/milestone</url> 
                
</repository> 
                
<repository> 
                    
<id>JBoss Repo</id> 
                    
<url>https://repository.jboss.org/nexus/content/repositories/releases</url> 
                    
<name>JBoss Repo</name> 
                
</repository> 
                
<repository> 
                    
<snapshots> 
                        
<enabled>false</enabled> 
                    
</snapshots> 
                    
<id>jboss repo</id> 
                    
<url>https://repository.jboss.org/nexus/content/groups/public/</url> 
                
</repository> 
                
<repository> 
                    
<snapshots> 
                        
<enabled>true</enabled> 
                    
</snapshots> 
                    
<id>JBoss Repo shapshots</id> 
                    
<url> https://repository.jboss.org/nexus/content/repositories/snapshots</url> 
                    
<name>JBoss Repo</name> 
                
</repository> 
                
<repository> 
      
<id>snapshots.jboss.org</id> 
      
<name>JBoss Snapshot Repository</name> 
      
<url>http://snapshots.jboss.org/maven2</url> 
      
<releases> 
        
<enabled>false</enabled> 
      
</releases> 
      
<snapshots> 
        
<enabled>true</enabled> 
      
</snapshots> 
    
</repository> 
                
<repository> 
                    
<snapshots> 
                        
<enabled>false</enabled> 
                    
</snapshots> 
                    
<id>Jolbox BoneCP</id> 
                    
<url>http://jolbox.com/bonecp/downloads/maven</url> 
                
</repository> 
            
</repositories> 
            
<pluginRepositories/> 
        
</profile> 
    
</profiles> 


</settings> 

posted @ 2011-10-30 20:57 paulwong 阅读(1686) | 评论 (0)编辑 收藏

HotSpot 的垃圾收集 - 转

从J2SE 5.0开始,HotSpot JVM共包含四种垃圾收集器,它们全部基于分代算法。
一、代的划分
HotSpot JVM中内存被划分为三代:年幼代(young generation)、年长代(old generation)和永久代(permanent generation)。从逻辑上讲,年幼代和年长代共同构成了Java堆,而永久代则被称为方法区(method area)。除了一些大对象可能在年长区中直接分配外,大部分对象都在年幼区中创建;而年长区除了那些直接创建的大对象外,大部分对象都是在年幼区中历经几次垃圾收集而幸免于难后被提升过来的。永久代中则保存着已载入类型的相关信息,包含了类、方法和其他一些内部使用的元数据,所有这些信息同样以对象的形式来组织和表示,虽然这些对象并不是Java对象,但是它们却象Java对象一样可以被同样的垃圾收集器所收集;另外,java.lang.String类所管理的内在化的字符串缓存池也在该代中分配;虽然名字叫做“永久”代,但其中的对象并不是永久的,只是沿用了历史名称而已。
年幼代由一个伊甸区(Eden Space)和两个更小的生还区(Survivor Space)组成,如下图所示(该图为缩略图,请点击察看原图)。大部分对象在伊甸区中创建,少数大对象可能在年长代中直接创建。生还区中保存的对象是历经一次或多次对年幼代的垃圾收集而未死的幸存者,并且在被认为已足够成熟而提升到年长代之前,它们仍有在稍后的某次垃圾收集过程中牺牲的可能。除非处在垃圾收集过程当中,两个生还区中只有一个用来容纳这些幸存者,另一个则保持为空。
JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s5.sinaimg.cn/bmiddle/51501580g8169fb66ab44&690">

二、垃圾收集类型
年幼代填满后,一次只针对该代的收集被执行,这样的收集也被称作“次收集(minor collection)”。当年长代或永久代被填满后,一次针对所有代的完整收集被执行,这样的收集也被称作“主收集(major collection)”。通常来说,在一次主收集过程中,年幼代首先被收集,收集算法采用当前收集器的年幼代收集算法,该算法往往是针对年幼对象的行为特征而专门设计的;然后是对年长代和永久代的收集,收集算法都采用当前收集器的年长代收集算法。对于给定收集器所具体使用的年幼代和年长代收集算法,请参考下文。另外,主收集过程中如果存在压缩,则每代独自进行。
不过,首先收集年幼代的策略在年长代空闲空间太小时会失效,因为年长代已无足够的空间来接纳所有的可能从年幼代提升过来的对象;在这种情况下,除CMS外的所有收集器都会放弃原有的年幼代收集算法,转而统一采用年长代收集算法对所有代进行收集。(CMS收集器之所以例外是因为它的年长代算法不能用来收集年幼代。)

三、快速分配
从下文对垃圾收集器的描述中可以看出,在许多情况下,内存中都有大块的连续空闲空间用以满足对象的分配请求。这种情形下的分配操作使用简单的“bump-the-pointer”技术,效率很高。按照这种技术,JVM内部维护一个指针(allocatedTail),它始终指向先前已分配对象的尾部,当新的对象分配请求到来时,只需检查代中剩余空间(从allocatedTail到代尾geneTail)是否足以容纳该对象,并在“是”的情况下更新allocatedTail指针并初始化对象。下面的伪代码具体展示了从连续内存块中分配对象时分配操作的简洁性和高效性:
void * malloc(int n){
if( geneTail - allocatedTail < n )
doGarbageCollection();
void * wasAllocatedTail = allocatedTail;
allocatedTail += n;
return wasAllocatedTail;
}
对于多线程应用,分配操作必须是线程安全的。如果使用全局锁为此提供保证,则分配操作必定成为一个性能瓶颈。基于此,HotSport JVM采用了一种被称为“线程局部分配缓冲区”(Thread-Local Allocation Buffers,TLAB)的技术。该项技术为每个线程提供一个独立的分配缓冲区(伊甸区的一小部分),借此来提高分配操作的吞吐量。因为针对每个TLAB,只有一个线程从中分配对象,故而分配操作可以使用“bump-the-pointer”技术快速完成,而不必使用任何锁机制;只有当线程将其已有TLAB填满并且需要获取一个新的TLAB时,同步才是必须的。同时,为了减少TLAB所带来的空间消耗,还使用了一些其他技术,例如,分配器能够把TLAB的平均大小限制在伊甸区的1%以下。
“bump-the-pointer”和TLAB技术的组合保证了分配操作的高效性,类似new Object()这样的操作在大部分时间内只需要大约10条机器指令即可完成。

四、收集方式
1)串行(serial)和并行(parallel)
串行和并行是从收集任务本身如何被完成的角度来描述收集过程的。采用串行方式收集时,同一时间只有一件事情会发生。例如,即使有多个CPU可用,还是只有一个被用来执行收集任务。当采用并行方式收集时,垃圾收集任务被分成许多子任务,并且那些子任务在不同的CPU上被同时执行。同时操作使收集任务得以更快地完成,代价是增加了任务的复杂性并可能产生内存碎片。2)STW(stop-the-world)和并发(concurrent)
STW和并发是从收集任务是否影响应用程序执行的角度来描述收集过程的。当垃圾收集使用STW方式进行时,在收集期间应用程序将被完全挂起。作为另一种选择,收集任务可以采取并发方式,与应用程序一起同时执行。比较典型的情况是,并发收集器采取并发方式完成大部分工作,但也可能偶尔地不得不切换到STW方式,以完成一些需要应用程序短暂停顿的工作。STW收集比并发收集更为简单,因为在收集期间堆被冻结、对象不会改变;它的缺点是对某些应用程序来说,被暂停过久是不符合要求的。相对地,采用并发方式进行垃圾收集时,停顿时间会更短,但这也要求收集器必须更加小心,因为它正在操作可能被应用程序同时更新的对象。对并发收集器来说,这会增加额外开销从而影响性能,也会对堆空间产生更大的需求。

五、串行收集器(serial collector)
使用串行收集器时,对年幼代和年长代的收集都采用串行、STW方式进行。也就是说收集任务同时只使用一个CPU,而且在收集任务执行期间,应用程序的执行被中止。
1)串行收集器如何收集年幼代?
下图展示了使用串行收集器对年幼代进行收集时的操作细节。伊甸区中的活动对象被拷贝到初始为空的生还区2中;已占用的生还区1中的活动对象如果仍显年轻,则同样被拷贝到生还区2中,否则被直接拷贝到年长代;需要注意的是,生还区2一旦被填满,则所有尚未被拷贝的活动对象,不论其来自伊甸区还是生还区1,也不论其曾经幸免于多少次次收集,统统被拷贝到年长代。按照定义,在活动对象被拷贝之后,伊甸区和生还区1中的对象就全部成为垃圾对象,无须再被检查。(垃圾对象在图中以“X”标记,虽然实际上收集器并不检查和标记这些对象。) JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s4.sinaimg.cn/middle/51501580g81cfe5708d93&690"> 收集完成后,伊甸区和生还区1变为空闲空间,活动对象保存在生还区2中。此时,两个生还区的角色已经发生了互换。如下图:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s4.sinaimg.cn/middle/51501580g81d362167ce3&690"> 2)串行收集器如何收集年长代?
串行收集器采用标记-清理-压缩算法收集年长代和永久代。在标记阶段,收集器遍历引用树,找出所有活动对象并打上标记;在清理阶段,顺序扫描代空间中所有对象(不论死活),计算出每个活动对象在代空间中的新位置;在压缩阶段,指向活动对象的所有引用被先期更新后,所有活动对象也被逐个滑动到其新的位置。由于所有活动对象都是按照次序朝代空间头部移动的,因此就在代空间尾部自然形成了一个单一而连续的空闲空间。如下图:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s3.sinaimg.cn/middle/51501580g81fd1aa883d2&690">压缩过程使基于年长代或永久代的分配操作可以使用快速的“bump-the-pointer”技术。
3)何时使用串行收集器?
对于运行在客户端级硬件上并且对停顿时间没有特别要求的大多数应用而言,串行收集器都是首选。按照目前的硬件水平,串行收集器可以高效地管理使用64MB堆空间、最长停顿时间不能超过半秒的很多重要应用。
4)串行收集器的选用
在J2SE 5.0版本中,对于非服务器级硬件而言,串行收集器作为缺省的垃圾收集器被自动选用;对于其他硬件平台,则可以通过命令行选项“-XX:+UseSerialGC”进行显示的选用。

六、并行收集器(parallel collector)
目前,许多Java应用的运行平台大都包含很多物理内存和多个CPU。并行收集器,也被称作吞吐量收集器,被开发出来的主要目的就是为了充分利用CPU资源,而不是只让一个CPU去做垃圾收集而其他CPU却被闲置。
1)并行收集器如何收集年幼代?
和串行收集器相比,并行收集器采用了大致相同的年幼代收集算法,只是执行的是其并行版本而已。对年幼代的收集虽然仍基于拷贝技术、采用STW方式进行,但收集工作是并行展开的,使用了多个CPU,这就降低了垃圾收集开销,从而提高了应用程序的吞吐量。下图展示了并行收集器和串行收集器在执行年幼代收集时到底有何不同:
JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s7.sinaimg.cn/middle/51501580g81e435e495a6&690">
2)并行收集器如何收集年长代?
和串行收集器一样,并行收集器对年长代的收集同样基于标记-清理-压缩算法,同样采用串行、STW方式进行。
3)何时使用并行收集器?
能够得益于并行收集器的应用程序,必定运行在多CPU机器上,并且对停顿时间不能有特别的约束。因为可能持续时间很长的年长代收集虽然稀少,但还是会发生的。适于采用并行收集器的典型应用包括批处理、记帐、工资单和科学计算等等。你可能更倾向于选择并行压缩收集器(见下文)而不是并行收集器,因为前者对所有代(而不只是年幼代)的收集都采用并行方式进行。
4)并行收集器的选用
在J2SE 5.0版本中,对于服务器级硬件而言,并行收集器作为缺省的垃圾收集器被自动选用;对于其他硬件平台,则可以通过命令行选项“-XX:+UseParallelGC”进行显示的选用。

七、并行压缩收集器(parallel compacting collector)
并行压缩收集器在J2SE 5.0 U6中引入,它和并行收集器的区别在于,对年长代的收集它使用了全新的算法。注意:并行压缩收集器终将取代并行收集器。
1)并行压缩收集器如何收集年幼代?
同并行收集器,不再赘述。
2)并行压缩收集器如何收集年长代?
使用并行压缩收集器时,对年长代和永久代的收集都采用带滑动压缩的准并行、STW方式进行。为了满足并行处理的要求,每一个代空间均被逻辑划分为诸多定长区域(fixed-sized region),每个区域的相关信息保存在收集器维护的内部数据结构中。收集过程被分为标记、汇总和压缩三个阶段进行。在标记阶段,根引用集被划分给多个垃圾收集线程,它们同时运行,以并行的方式对活动对象进行追踪和标记;在活动对象被标记的同时,该对象的起始区域的数据也将被同步更新以反映该活动对象的大小和位置信息。
在汇总阶段(summary phase),操作不再基于对象,而是区域。考虑到先前收集过程中的压缩累积效应,每一个代空间中位于左侧的某一部分通常是密集的,主要包含了活动对象。从这样的密集区块中可能回收的空间数量使得它们并不值得被压缩。所以汇总阶段的首要任务就是检查区域的密集度,从最左边一个区域开始,直到找到这样的一个区域,使得在该区域及其右侧所有区域中可被回收的空间数量抵得上对它们进行压缩的成本。该区域左侧的所有区域就被称为密集前置区块,没有对象会被移入其中。该区域及其右侧所有区域会被压缩,以消除所有死区。汇总阶段的下一个任务就是计算并保存每个被压缩区域中活动数据的首字节在压缩后的新位置。需要注意的是:汇总阶段在目前被实现为一个串行阶段,这也是“准”并行方式的由来;并行实现也是可能的,只是与标记和压缩阶段的并行化相比,它对性能的影响不大。
在压缩阶段,垃圾收集线程使用汇总数据确定需要被填充的区域,然后它们就可以独立地把对象拷贝到这些区域中而不再需要额外的同步。这就产生了一个堆,堆空间的一端塞满了活动对象,而另一端则是一个单一而连续的空闲内存块。
3)何时使用并行压缩收集器?
和并行收集器一样,并行压缩收集器同样有益于在多CPU机器上运行的应用程序。除此之外,年长代收集的并行化操作方式还减少了停顿时间,使得并行压缩收集器比并行收集器更为适合那些有停顿时间限制的应用。不过,对于运行在大型共享主机(如SunRays)上的应用来说,并行压缩收集器也许并不太合适,因为任何单一应用都不应长时间独占几个CPU。在这样的机器上,要么考虑通过命令行选项“-XX:ParallelGCThreads=n”减少垃圾收集线程的数目,要么考虑选择一种不同的收集器。
4)并行压缩收集器的选用
并行压缩收集器只能通过命令行选项“-XX:+UseParallelOldGC”进行显示的选用。

八、并发的标记-清理收集器(Concurrent Mark-Sweep(CMS) Collector)
对于许多应用来说,端到端的吞吐量并不象响应时间那么重要。通常来讲,对年幼代的收集并不会引起太长时间的停顿。但是对年长代的收集,虽然不常发生,却可能导致停顿时间过长的状况,在堆空间很大时尤其明显。为了解决这个问题,HotSpot JVM包含了一个名叫“并发的标记-清理(CMS)收集器”的收集器,它也被称为低延迟收集器。
1)CMS收集器如何收集年幼代?
同并行收集器,不再赘述。
2)CMS收集器如何收集年长代?
采用CMS收集器收集年长代时,大部分收集任务与应用程序并发执行。
CMS收集器的收集周期始于初始标记,它采用串行、STW方式进行,用于确定根引用集。随后进入并发标记阶段,完成对所有活动对象的追踪和标记,在JDK6中该阶段已开始采用并行、并发方式进行。由于在并发标记过程中应用程序正在执行并可能更新了一些对象的引用域,因此并发标记过程结束时并非所有活动对象都已确保被标记出来。为了处理这种情况,应用程序再次暂停,收集过程进入再标记阶段;它采用并行、STW方式进行,通过对并发标记过程中被修改对象的再次访问最终完成整个标记过程。因为再标记阶段的停顿时间往往是最长的(超过初始标记停顿甚至次收集停顿),因此再标记过程会尽量采用并行方式进行。
再标记阶段完成后,所有活动对象都已确保被标记,随后进入并发清理阶段,它采用串行、并发方式进行,就地回收所有垃圾对象。下图展示了串行的标记-清理-压缩收集器和CMS收集器在收集年长代时的区别: JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s13.sinaimg.cn/middle/51501580g82676852d74c&690"> 因为一些任务(例如再标记过程中对被修改对象的再次访问)增加了收集器的工作量,CMS收集器的总体开销自然会增大。对于大多数试图减少停顿时间的收集器来说,这是一种典型的折衷。
CMS收集器是唯一一个不使用压缩技术的收集器。也就是说,在垃圾对象所占用的空间被释放以后,收集器并不把活动对象全部推挤到代空间的某一端去。见下图:JVM中的垃圾收集" alt="HotSpot JVM中的垃圾收集" src="http://s3.sinaimg.cn/middle/51501580g82716466bed2&690">这种方式节省了回收时间,但却因为空闲空间不再连续,收集器也就不再可能只使用一个简单指针即可指示出可分配给新对象的下一个空闲空间的位置,相反,它现在需要使用空闲空间列表。也就是说,收集器创建并通过一组列表把内存中尚未分配的区域连接起来,每当有对象需要分配空间时,适当的列表(基于所需内存数量)被搜索,以找到一块足以放下该对象的空闲区域。作为结果,与使用“bump-the-pointer”技术时相比,年长代中的分配操作变得更加昂贵。同时这也给年幼代收集带来了额外的开销,因为在其收集过程中每提升一个对象都会触发一次年长代中的分配操作。
CMS收集器的另一个缺点是和其他收集器相比它需要更大的堆空间。一方面,由于在标记阶段应用程序被允许运行,它就可能继续分配内存,从而可能使年长代空间不断地增长;另一方面,虽然标记阶段完成后所有活动对象都已确保被标记,但是在标记过程中一些对象却可能变为垃圾对象,而且直到下次年长代收集之前它们不会被回收。这样的对象也被称为游浮垃圾。
CMS收集器的最后一个缺点是由于缺乏压缩它可能引发碎片化问题。为了对付碎片化,CMS收集器跟踪对象的流行尺寸,预估未来需求,并为满足需求还可能分割或合并空闲内存块。
不象其他收集器,CMS收集器并不是等到年长代填满后才启动对年长代的收集,而是尝试尽早启动年长代收集,以便在年长代被填满之前收集过程可以完成。否则的话,CMS收集器将重新采用在串行和并行收集器中使用的标记-清理-压缩算法,尽管该算法工作于STW方式,也更加耗时。为避免这种情况的发生,CMS收集器对先前收集所耗时间和代空间充满所耗时间进行统计,并据此确定收集启动时间。另外,当年长代的空间占用率超过启动占用率(initiating occupancy)时,CMS收集器也将启动一次收集。启动占用率的值可以通过命令行选项“-XX:CMSInitiatingOccupancyFraction=n”进行设定,其中 n 表示年长代空间大小的百分比。缺省值为68。
总的来说,与并行收集器相比,CMS收集器(有时甚至显著地)减少了年长代收集的停顿时间,而代价是略有增加的年幼代收集的停顿时间、吞吐量方面的一些损失和额外的堆空间需求。
3)增量模式
CMS收集器可以采用让并发阶段增量完成的模式运行。这种模式通过对并发阶段的周期性暂停把处理能力交还给应用程序,以减少并发阶段持续时间过长所带来的不利影响。收集工作被分成许多小的时间块,它们在年幼代收集的间歇期被调度。当应用程序既需要CMS收集器提供的低停顿时间,又只能在很少的CPU(比如说1到2个)上运行时,这个特性就相当有用。
4)何时使用CMS收集器?
如果应用程序需要更短的垃圾收集停顿时间并且能够承担在运行时和垃圾收集器共享处理器资源,那么就可以使用CMS收集器。(由于其并发性,在垃圾收集过程中CMS收集器将和应用程序抢夺CPU周期。)通常来说,具有较大的长寿数据集并且运行在2个或多个CPU上的应用程序,更容易受益于CMS收集器的使用。一个典型的例子就是Web服务器。对于任何需要低停顿时间的应用程序来说,CMS收集器都值得考虑。对于年长代尺寸适中并且运行在单一处理器上的交互式应用程序来说,使用CMS收集器同样可能取得不错的效果。
5)CMS收集器的选用
CMS收集器只能通过命令行选项“-XX:+UseConcMarkSweepGC”进行显示的选用。如果希望CMS收集器在增量模式下运行,还需要通过命令行选项“-XX:+CMSIncrementalMode”启用该模式。

九、收集器、堆尺寸和虚拟机的自动选择
在J2SE 5.0中,根据应用程序所运行的硬件平台和操作系统,垃圾收集器、堆尺寸和HotSpot虚拟机(客户机或服务器)的缺省值被自动选定。这些自动的选择不仅减少了对命令行选项的使用,而且还更好的满足了不同类型应用程序的需要。
1)服务器级硬件(server-class machine,不使用“机器”这个词是因为读起来太拗口)的定义:
服务器级硬件必须同时满足以下两个条件:
①拥有2个或以上的物理处理器
②拥有2GB或以上的物理内存
该定义适用于所有平台,32位Windows平台除外。
2)服务器级硬件与非服务器级硬件下各项缺省值的比较:
机器类型 虚拟机 垃圾收集器 堆尺寸初始值-Xms 堆尺寸最大值-Xmx
服务器级硬件 服务器版 并行收集器 物理内存的1/64,不超过1GB 物理内存的1/4,不超过1GB
非服务器级硬件 客户机版 串行收集器 4MB 64MB
注意:本节所涉及的堆尺寸指的是Java堆的大小,包括年幼代和年长代,但不包括永久代。  

posted @ 2011-10-30 20:47 paulwong 阅读(326) | 评论 (0)编辑 收藏

架构设计的一些关键点

eBay 架构经验
  1. Partition Everything 切分万物
  2. Asynchrony Everywhere 处处异步
  3. Automate Everything 全部自动
  4. Remember Everything Fails 记录失败
  5. Embrace Inconsistency 亲不同是谓大同
  6. Expect (R)evolution 预言演变
  7. Dependencies Matter 重视依赖
  8. Be Authoritative 独断专行
  9. Never Enough Data

淘宝架构经验
  1. Partition Everything 切分万物
  2. 适当放弃一致性
  3. 备份和隔离解决稳定性问题
  4. 分割和异步解决性能问题(类似 eBay 的 Asynchrony Everywhere)
  5. 自动化降低人力成本(类似 eBay 的 Automate Everything)
  6. 产品化管理

Flickr架构经验
  1. 使得机器自动构建 (Teach machines to build themselves)
  2. 使得机器自监控(Teach machines to watch themselves)
  3. 使得机器自修复(Teach machines to fix themselves)
  4. 通过流程减少 MTTR (Reduce MTTR by streamlining)

架构的关注点是系统。其全名本来也是系统架构。它是系统级的主题。它当然也属于系统设计过程的一个部分。只是与面向对象聚焦于业务领域不同,它聚焦于解决所有系统共同的问题,或者说与业务逻辑无关的问题。
上面所列出的技术,其实可以全部归结为对以下技术的采用:
  1. 自动化
  2. 错误记录
  3. 异步
  4. 接受不一致性即适当地放弃正确性
  5. 对系统进行适当的抽象定义(横向与竖向。模块与方面。数据分割。。。模块,方面,分割的数据都是一种抽象。定义是为了管理。没有定义就没有管理。定义是管理的前提。要不然,“管理”什么?)
  6. 可进化性
  7. 面向用户(即产品化。产品化指的是从产品的角度对产品进行包装,,包括产品服务,错误,交互,UI等等)
  8. 隔离(管理依赖--剔除不必要的依赖,管理必要的依赖)
  9. 使得机器自监控(Teach machines to watch themselves)

posted @ 2011-10-30 20:29 paulwong 阅读(273) | 评论 (0)编辑 收藏

在LINUX下配置JBOSS

  1. bin/run.sh
    export LANG=zh_CN.GB18030 //使用中文
    JBOSSCONF
    ="default" //SERVER中使用default
  2. bin/run.conf
    配置JAVA_OPTS
    if [ "x$JAVA_OPTS" = "x" ]; then
       JAVA_OPTS
    ="-Xms512m -Xmx2048m -XX:MaxPermSize=256m -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dsun.lang.ClassLoader.allowArraySyntax=true -Djava.awt.headless=true "
       JAVA_OPTS
    ="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
    #   JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Djboss.platform.mbeanserver -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl"
       JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=10.0.122.132"
    fi
  3. /opt/jboss4.3/jboss-as/server/default/deploy/jboss-web.deployer
    改端口和绑定监听所有的IP
        <Connector port="80" address="0.0.0.0"    
             maxThreads
    ="250" maxHttpHeaderSize="8192"
             emptySessionPath
    ="true" protocol="HTTP/1.1"
             enableLookups
    ="false" redirectPort="8443" acceptCount="100"
             connectionTimeout
    ="20000" disableUploadTimeout="true"
        compressableMimeType
    ="text/html,text/xml,text/plain,text/css,text/javascript,application/xhtml+xml,application/x-javascript,application/javascript,text/xhtml" />
  4. /opt/jboss4.3/jboss-as/server/default/conf/
    配置LOG4J
       <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
          
    <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
          
    <param name="File" value="${jboss.server.log.dir}/server.log"/>
          
    <param name="Append" value="true"/>
          
    <param name="Threshold" value="ERROR"/>

          
    <!-- Rollover at midnight each day -->
          
    <param name="DatePattern" value="'.'yyyy-MM-dd"/>

          
    <!-- Rollover at the top of each hour
          <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
          
    -->

          
    <layout class="org.apache.log4j.PatternLayout">
             
    <!-- The default pattern: Date Priority [Category] Message\n -->
             
    <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>

             
    <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n 
             <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
        
    -->
          
    </layout>
       
    </appender>
  5. /etc/profile
    配置JAVA_HOME等,改完后source /etc/profile,使配置生效
    JAVA_HOME=/usr/java/jdk1.6.0_29
    JRE_HOME
    =/usr/java/jdk1.6.0_29/jre
    PATH
    =$JAVA_HOME/bin:JRE_HOME/bin:$PATH 
    CLASSPATH
    =.:$JAVA_HOME/lib/jt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib 
    export JAVA_HOME JRE_HOME PATH CLASSPATH 
  6. 相关LINUX命令
    # cd /usr/local/jboss-4.2.3.GA/bin 
    #./run.sh //jboss的启动
    #tail -f nohup.out //查看启动信息
    #./shutdown.sh -S //jboss的停止
    #ps -ef |grep java //查看jboss的运行状态
    #kill -9 后加PID //杀进程
    #netstat -ntpl //查看端口
    #iptables -F //清除所有防火墙限制

posted @ 2011-10-28 10:18 paulwong 阅读(1471) | 评论 (0)编辑 收藏

开放 linux 防火墙 端口

想搭个服务器,但外面访问不到,是防火墙的原因,把端口设置一下就行。

1.在/etc/sysconfig/iptables里添加
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -ACCEPT

2.重启iptables
[root@localhost ~]# /etc/init.d/iptables restart

3.看下状态
[root@localhost ~]# /etc/init.d/iptables status

posted @ 2011-10-27 10:15 paulwong 阅读(155) | 评论 (0)编辑 收藏

JDK线程查看工具

JDK和LINUX提供的查看当前运行的线程的工具: 
  1. KILL
    kill -3 [pid]:线程相关信息会列在Console上
  2. JSTACK
    jstack [pid]:查看线程运行状况,如等锁,运行等
  3. JCONSOLE
    jconsole -pluginpath [JTop.jar]:增加一个JTOP的标签,可查看所有线程
    TthreadXMBean:在JCONSOLE中访问此BEAN即可

posted @ 2011-10-27 00:04 paulwong 阅读(1350) | 评论 (0)编辑 收藏

JDK内存管理工具比较

JDK自带了不少查看和管理内存的工具:
  1. JMAP
    jmap -heap [pid] : 文字形式查看JVM中堆内存,非堆内存等大小情况
    jmap -histo [pid] : 文字形式查看各种类占内存大小情况,但粒度只去到[C这种
    jmap -dump:format=b,file=文件名 [pid] : DUMP出内存快照,给其他工具分析内存提供依据
  2. JHAT
    jhat -J-Xms1024M 文件名:分析DUMP文件,并将结果以http://ip:7000向外提供,可具体到哪些对象
  3. MAT
    由于jhat分析大文件时速度慢,因此引入Eclipse Memory Analyzer,速度和功能强很多
  4. JSTAT
    jstat -gcutil [pid]:查看FULL GC的次数和消耗时间,统计
  5. JCONSOLE
    以图形方式查看内存、线程、类、MBEAN等信息
  6. JVISUALVM
    是JCONSOLE的升级版,可查看内存、线程、各对象占内存的大小,JMAP/JHAT能做的都可以做到

能用图形查看的就用图形方式查看,不能的就用文字形式代替。

posted @ 2011-10-26 23:51 paulwong 阅读(886) | 评论 (0)编辑 收藏

配置远程JCONSOLE

JDK自带工具JCONSOLE,可以以图形界面远程监控JVM的情况,也可作相应的一些操作。
1、修改Tomcat的启动语句,将bin/catalina.sh文件vi编辑:
将原
JAVA_OPTS="-Xmx1024M -Xms512M -Xss3M"
export JAVA_OPTS
调整为
JAVA_OPTS="-Xmx1024M -Xms512M -Xss3M -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true"
export JAVA_OPTS
如果是JBOSS,还需加这一行
JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=10.0.122.132",如果不加就连不上

检查LINUX环境:
运行:hostname -i,如果返回127.0.0.1,则要改/etc/sysconfig/network里的HOSTNAME为NEWHOST,再在/etc/hosts里增加一行本机IP对应NEWHOST的值。
清除防火墙的所有东西:iptables -F!!
参考:http://dikar.iteye.com/blog/534109

2、修改jmx配置文件
目录切换至JAVA_HOME所在目录
/jre/lib/management下,
a、将jmxremote.access、jmxremote.password.template权限调整为读写;
chmod 600 jmxremote.password.template
chmod 600 jmxremote.access
b、jmxremote.password.template文件重命名
mv jmxremote.password.template jmxremote.password
c、vi jmxremote.password
去掉
# monitorRole QED
# controlRole R&D
的#号(Solaris下可编辑模式下,可以使用x删除光标标记处字符)
:wq 保存操作
3、启动Tomcat
./catalina.sh run

4、查看JMX启动情况
netstat -a | grep -i 9999 查看端口占有情况
如机器9999端口被其他程序占用,可调整端口-Dcom.sun.management.jmxremote.port=????

5、客户端机器可通过jconsole或visualvm对其进行监控
使用JMX方式,输入url 用户名(controlRole)、密码(R&D)即可访问
url:远程主机IP:9999
用户名及密码(参考jmxremote.password文件) monitorRole只能读,controlRole能读写

配置中的安全原因出错,由于密码是以明文的方式保存在:jmxremote.password中,所以对此文件只能有所有者都读取,其他人都不能读取。WINDOWS下的设置情况见:http://1985wanggang.blog.163.com/blog/static/77638332010731101726156/

JCONSOLE使用手册:
1.5:http://blog.sina.com.cn/s/blog_5dc29fcc0100xiex.html
1.6:http://hornetblog.sinaapp.com/?p=5

posted @ 2011-10-26 22:31 paulwong 阅读(2208) | 评论 (0)编辑 收藏

JVM参数调优

JVM中用来放NEW出来的对象的内存叫堆内存,用来放CLASS等静态的对象的内存叫非堆内存,如果不加指定,默认情况下就几十兆。当遇上一些饭量大的家伙,如POI,导出上万条数据时,就会报内存溢出。所以在生产环境要指定这些内存的大小。

-server
一定要作为第一个参数,会使JVM启动速度变慢,但会显著提升JVM性能

-Xms<size>
设置初始化时堆内存大小,有多大就设多大。设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

-Xmx<size>
设置堆内存最大值,有多大就设多大

-XX:PermSize=300M
设置初始化时非堆内存大小,一般为总内存的1/8

-XX:MaxPermSize=300M 
设置非堆内存最大值,一般为总内存的1/4

-Xmn2g:设置年轻代大小为2G.整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8.

-Xss128k: 设置每个线程的堆栈大小.JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右.

-XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代).设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5

-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值.设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6

-XX:MaxTenuringThreshold=0: 设置垃圾最大年龄.如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概论.

回收器选择
JVM给了三种选择:串行收集器,并行收集器,并发收集器,但是串行收集器只适用于小数据 量的情况,所以这里的选择主要针对并行收集器和并发收集器.默认 情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数.JDK5.0以后,JVM会根据当前系统配置进行判断.
吞吐量优先的并行收集器
如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等.
典型配置:

-XX:+UseParallelGC
选择垃圾收集器为并行收集器.此配置仅对年轻代有效.即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集.

-XX:ParallelGCThreads=20
配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收.此值最好配置与处理器数目相等.

-XX:+UseParallelOldGC
配置年老代垃圾收集方式为并行收集.JDK6.0支持对年老代并行收集.

-XX:MaxGCPauseMillis=100
设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值.

-XX:+UseAdaptiveSizePolicy
设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开.

参考资料


Tomcat – Java.Lang.OutOfMemoryError: PermGen Space
http://www.mkyong.com/tomcat/tomcat-javalangoutofmemoryerror-permgen-space/


实例讲解JVM参数调优的八条经验
http://developer.51cto.com/art/200907/134761.htm

posted @ 2011-10-25 20:43 paulwong 阅读(348) | 评论 (0)编辑 收藏

仅列出标题
共110页: First 上一页 90 91 92 93 94 95 96 97 98 下一页 Last