`
nlslzf
  • 浏览: 1044961 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

看JTS源码,感受Java优化编程

    博客分类:
  • java
阅读更多
看JTS源码,感受Java优化编程
http://www.blogjava.net/sinoly/archive/2007/02/11/99205.html
2007年以来,从Geotools、PostGIS到JTS Topology Suite再到java优化编程感受,看似过程相当的复杂,而且相当的凌乱。呵呵,都是Geotools惹的祸呀,没有办法,为了能深度使用Geotools我只能研究JTS Topology Suite,在学习JTS过程中又有一些感想,呵呵,其实从目的而言跨度没有那么大,只是一个磨刀不误砍柴功的过程。    

       读了一些JTS的源码,呵呵,不对不是一些,而只是com.vividsolutions.jts.geom中的一部分那,还不到整个JTS Topology Suite源码的1/10的代码,对其实现思路可能还不是很清晰,但是看着大拿们写的代码还是让我觉得很有收获。这些收获有我以前没有感受的,也有以前知道原理但是就是不去重视的内容。写在这些文字当作是对自己编程风格的一篇械文。也希望在学习JTS的过程中能从大拿们的代码中学习到更多的内容,最终使得自己不仅仅学习这些编程大拿成果的使用,更使自己能提高自己的代码质量。

      作为自己对Java优化编程感受的开篇,还是从最基础的GC开始吧。呵呵,毕竟GC的存在是Java的特色之一,但是如果完全依托于JVM中的GC就想获取良好的程序效率太困难了,这一点相信很多人都有一个清楚的认识。如何合理的使用Java回收机制,如何让GC更快的实施回收,我想也许很多程序员和我一样都不是很重视,所以先来抛个砖,让朋友们一起来批判一下。

     (一下文字中有一些引用了曾经看过的《JVM初探》、《Java的GC机制》等牛人文章,由于时间太长,很多定义我无法记住来源,所以就不一一标明了。望原作者谅解!ps:标题貌似是这个)

     Java程序中的内存管理机制是通过GC完成的,“一个对象创建后被放置在JVM的堆内存中,当永远不在应用这个对象的时候将会被JVM在堆内存中回收。被创建的对象不能再生,同时也没有办法通过程序语句释放”(这个是《Java的GC机制》中提到的定义,呵呵,还依稀记得)这就是GC对垃圾对象的定义。个人感觉这么解释或许会比较快理解:在运行环境中JVM会对两种内存进行管理,一种是堆内存(对象实例或者变量),一种是栈内存(静态或非静态方法),而JVM所管理的内存区域实际上就是堆内存+栈内存(MS:对象实例+实例化变量+静态方法+非静态方法),当JVM在其所管理的内存区域的中无法通过根集合到达对象的时候就会将此对象作为垃圾对象实施回收。

      Java所有的对象都有一个生命周期:创建、使用、不可视、不可到达、回收释放。先就从这个过程中结合昨天(2月9日)10点到今天(2月10日)凌晨2点看JTS代码的一些感受,对自己来个自我批评吧,同时也对自己的一些经验做一次总结(呵呵,在老爸家,无法上网,都不知道什么时候可以帖到Blog去)

创建阶段
          先来看看我从JTS代码中感受到我需要立刻改正的错误,虽说理论上我明白道理,但是我就是没有去做过,也许这就是大师和大师兄的区别吧。。。汗自己一个。。。

          我的代码中曾经出现过这样的代码:

          List alist=uSvr.getUserinfoList();

          for(int i=0;i<alist.size();i++){

             //首先这里就有问题,这个是Crespo小兄弟给我提出的。最好使用for(int i=0 p=alist.size();i<p;i++),避免alist由于在循环体中发生变化时所带来的问题,而且即便alist没有发生变化,这么做也避免程序不断去执行size()方法所带来的资源损耗。赞一个先,因为Crespo所提到的思路在JTS代码中大师们都这么干,而且也绝对应该这么干

              Object obj=new Object();

              //这里问题大了。创建对象第一忌:不要在循环体中创建对象。这种做法会在内存中保存N份这个对象的引用//会浪费大量的内存空间(虽说内存便宜,可以进行硬件升级),同时JVM的GC机制会因为这些无谓的对象做大量//的回收工作,系统不慢都不行呀。。。好在这个问题很早以前就被我注意了,现在我的做法时在循环体外首先声明一个空对象,然后在循环体内new一个出来。

              。。。 。。。

         }

        现在我写的代码中出现这种情况

        public class Test{

           Object obj=new Object();

           public Test(){

              obj=new Object();

             //我的代码将Object对象初始化了两次。这个给内存带去的消耗绝对不比在循环体中创建对象来得小。创建对象第二忌:尽可能不要多次初始化对象。我这个问题也是恰好这两天在给一个公司做一个SP数据转发的开发中写过的。看JTS的大师们的代码在想流程的时候,偶然发现这个问题,但是那个汗呀。。真的。。汗流成河。。。

          }

       }

       除了上面两大忌讳外,对象在创建过程中还需要注意到以下问题。不采用过深的集成关系;访问本地变量由于访问类变量。这两点很多书都有提到。

使用阶段
       其实对象在使用阶段的优化,JTS的源码给我了一种提示,那就是java.lang.ref的有效利用。这个包实际上我今天是第一次看,从来都没有注意过这个包的使用问题,虽说它属于java.lang核心开发API中的范畴。知道看到JTS源码中出现这个代码我才“带着这玩意干什么的?”的疑问翻了一下API。

       结合JTS源码中的写法以及所查阅的API的内容,说说我的感受吧。首先在java.lang.ref包中最值得我们多关注的是如何合理的使用SoftReference以及WeakReference。也就是我么那如何将我们的对象置为软引用和弱引用。在API上有软引用以及弱引用的详细解析,俺就不JY了,哪些人更不得了,都是火星派来介绍地球什么叫Java的外星人。很是先看看JTS代码中大师们的程序风格吧:



     Object obj = new  Object();

     使用obj对象过程

    SoftReference softReference = new  SoftReference(obj); // 将obj设置为软引用类型

    obj = null ; // 强制释放引用

     // obj对象再次使用时应该做的处理

      if (softReference != null ) {

        obj = softReference.get();

     } else {

       obj = new  Object();

    }



        老实话,第一眼看到这样的代码我很惊讶,这tmd不是无聊吗?用了obj对象就直接仍到SoftReference(哪时候还以为是JTS自己的一种缓存机制)不说还要强制释放,第二次引用要么用get方法取,要么重新初始化,这不是没事找事情吗?唉,真是差距呀。。。OutOfMemory错误我一直都不在意,认为那是硬件问题,我不管。可是看看大师们,为了更加有效的节约资源所作的工作吧,这些东西增加了少量的程序工作量,可是对于系统资源使用效率以及程序执行效率的提升确实是很大的首先将对象设置为软引用,然后强制释放,将资源流出来给其他对象,当程序需要在此使用这对象得时候要么从softReference(其实也可以看作是简单缓存)中将原有对象还原,要么由于被GC回收了软引用,再重新初始化一次。。。。(所以说研究出Java的人都是火星上来的,居然考虑得如此周密)

     弱引用方法河软引用方法一样。他们之间得区别在于弱应用能更快得被GC给回收,毕竟软应用只是再内存使用到达警戒水平的时候才会进行。结合JTS目标是处理空间数据以及空间拓扑,它处理的对象很多都是一种Map结构的对象,这种对象会占用大量的内存空间,所以我们很好理解JTS为什么做了这么多我们平时再代码中从来不注意的事情。但是这不代表因为我们的系统目标和JTS不一样,所以我们就可以不去做这些工作。

不可视阶段
          什么样的对象可以将其认定为不可视阶段呢?举个例子吧,在try{...}catch(Exception){...}代码中,如果在try的代码块中声明了一个obj,那么当整个 try{...}catch(Exception){...}代码段执行完毕以后这个obj实际上就已经属于不可视阶段了。在JTS源码中我看到很多这样的例子,大师们会在try代码块的最后多一句话:obj=null;实际上这种方式我也使用过,但是99%的时候都用所谓的项目时间紧张为借口忽略了。其实多这么一句话将obj对象置为空值可以快速的帮助JVM发现这个对象,并进行回收以释放资源。这里也有一部分代码是使用的SoftReference来处理,呵呵,大师的风格也不尽相同呀。

         当然,即便没有这句话最终这个对象会被GC给回收,但是快速的释放资源就可以有效的提高现有资源的利用效率,这个难道真的不应该被我们这些使用高级编程语言进行开发的程序员所提倡吗?资源永远都是有限的,并非只是汇编或是做嵌入式开发的程序员才应该关注程序使用资源的问题的!改编周星星名言-“程序不是这样写的!资源不是这么用的!”

不可到达/回收释放阶段
          一个对象混到这份上就也该知足了,也该自觉一点轻轻走了算了,就算不走GC作为警察(户籍警察)也会对此对象实施强制消户了。。。一般情况下我还是不相信这个世界上有鬼存在的,那些怎么打也打不死的青铜圣斗士除外。。。。



      其他方面据不完全统计的个人经验而言,在开发过程中做到1、不提前创建对象,什么时候用什么时候创建;2、数组创建时尽可能避免显示申请数据的内存空间;3、当对象占用资源大&对象数据稳定&对象生命周期长可能的使用静态变量;4、使用IDE编译代码的时候在程序的发布版本编译时去掉IDE默认的debug编译模式(Eclipse:窗口-首选项-java-编译器)、在需要同类大量对象的时候,使用对象池,数据库连接池即在次范围。。。 。。。同时没有事情的时候多多学习大师的代码,java开源社区有很多值得学习代码风格的源代码等待着我们呢:)



附上代码来解释一下堆内存和栈内存的区别

(阅读许可证:本实例代码未满18岁或家有女王者勿入,由本代码引起的一切纠纷、人身伤害以及法律问题需阅读者自行解决,原创作者 sinoly 不承担任何责任。一旦阅读本代码,就表示你已接受本许可所提出的所有观点)



public   class  我的老婆们 {

static  Vector 老婆s = new  Vector(); // 创建一个老婆的Vector序列

static   void  娶个老婆() {     

      PLMM plmm  =   new  PLMM(); // 请首先new一个PLMM对象

      老婆 wife = (老婆)plmm ; // 不作此做出方法解释,涉及到太多问题

      老婆s.AddElement(老婆); // 本方法多次运行可实现了一夫多妻的宏伟目标,也是本人长期努力的方向

}

public   static   void  main(String[] args) {

      娶个老婆(); // 执行此方法可能会带来内存溢出,请慎重!

}

}



栈内存中存放的内容:main,娶个老婆()

堆内存中存放的内容:我的老婆们,我的老婆们.老婆s,Vector,plmm,老婆

NOTE:堆内存是在JVM启动的时候创建,堆内存分为新对象与老对象。对于新对象好像会分三个区域。当优先级最高的区域的堆栈满了以后JVM将会进行测试,测试内容是那些对象不可到达,不可到达的对象将会放入到老对象区域。同时JVM会将所有对象拷贝到另外两个区域中,然后经过一段时间依然没有引用的对象会进入老对象区域。对于老对象区域而言基本上就是等待被GC回收的对象了。(这些还是在大学时学.net时候的知识,直接换成java定义我想其中概念应该一样。唉,大学毕业到现在快5年了--真的老了,唉!看着周围83年甚至85年的同事,真的很伤自尊呀!)

ps:拜托各位看官千万不要把前一段代码和这个NOTE结合起来联想,会死人的!
分享到:
评论

相关推荐

    无人机后端开发java无人机后端开发java

    Java的`java.net`和`java.nio`包提供了丰富的网络编程接口。 3. **实时性与并发处理** 无人机系统通常需要处理大量的实时数据,如GPS坐标、传感器读数等。Java的并发API(如ExecutorService、Future、Callable、...

    JTS中文API.rar

    Java Transaction Service(Java事务服务)拓扑套件,是一种能够利用清楚精确的模型和强大的几何算法来实现一套核心空间数据操作的JAVA 应用编程接口(API)。它提供一种详细说明2-D线性几何图形(Geometry)的完善...

    yu_java_earthxjb_源码.zip

    总的来说,理解“yu_java_earthxjb”源码需要结合Java编程、GIS原理、特定GIS库的使用,以及数据处理和网络通信等方面的知识。通过深入阅读和分析源码,不仅可以掌握项目的工作机制,还能为自己的开发实践提供宝贵的...

    基于java的ArcGIS切片解析

    总的来说,“基于Java的ArcGIS切片解析”是一个结合了GIS专业知识和Java编程技术的项目,它涉及地图服务、空间数据处理、文件解析等多个领域,对于提升开发者在GIS领域的技能和Java编程能力具有很高的价值。

    jsp公交查询系统源码(java开发)

    【标题】"jsp公交查询系统源码(java开发)"是一个使用Java技术和JSP(JavaServer Pages)编写的公交查询应用程序。这个系统旨在为用户提供一个方便的平台,以查询城市的公交路线信息。通过这个系统,用户可以输入...

    JTS官方开发指南中文翻译版.doc

    在开始使用JTS之前,需要了解Java编程语言和OGC标准的基本概念。同时,需要安装JDK和Eclipse开发环境。 三、处理空间关系 JTS提供了多种空间关系操作,包括点、线、面等几何对象的相交、包含、相邻等关系。这些操作...

    javamap.rar_源码

    在本项目"javamap.rar_源码"中,我们可以看到一个使用Java编程语言实现的电子导航仪系统。这个系统允许用户自定义起点和终点,从而实现路线规划和导航功能。下面将对这个项目的相关知识点进行详细阐述。 首先,我们...

    Java中Enterprise JavaBeans(EJB)编程实例代码.rar

    Java中Enterprise JavaBeans(EJB)编程实例代码,内容有:简单的EJB、无状态SessionBean、有状态SessionBean、BMP位图实例、cmp实例、Message-Driven Bean、JNDI的使用、112各种EJB之间的调用、B-S结构EJB、 C-S结构...

    基于Java的gis地图应用 .zip

    1. **Java编程基础**:首先,你需要熟悉Java的基本语法、面向对象编程概念以及异常处理等基础知识。这将帮助你理解代码结构和功能。 2. **图形用户界面(GUI)**:GIS应用通常需要一个交互式的用户界面,这可能涉及...

    Java中的EJB编程实例代码

    Java中的EJB编程实例代码,内容有:简单的EJB、无状态SessionBean、有状态SessionBean、BMP位图实例、cmp实例、Message-Driven Bean、JNDI的使用、112各种EJB之间的调用、B-S结构EJB、 C-S结构EJB、UML建模与J2EE...

    java+js+不规则区域地图+中国+省份+加亮图源码整理

    "Java + JS" 指的是两种编程语言的结合,Java通常用于服务器端处理,而JavaScript则常用于客户端交互。在这个项目中,Java可能负责后端数据处理和地图数据的生成,而JavaScript则可能负责前端的地图展示和用户交互,...

    R树的Java实现

    标题中的“R树的Java实现”指的是在Java编程语言中如何构建和操作R树数据结构。R树是一种多维空间索引数据结构,常用于地理信息系统、数据库索引和图像检索等领域,它能够高效地存储和查询高维数据。下面将详细介绍R...

    jdk1.6源码

    Java Development Kit (JDK) 是Java编程语言的核心组件,它包含了一个Java运行环境、编译器、类库以及用于创建和部署Java应用程序的各种工具。在本资源中,我们聚焦于JDK 1.6版本的源代码,这为开发者提供了一个深入...

    java 读写Shape库

    Java 读写Shape库主要指的是在Java环境中操作ESRI...总的来说,Java中的Shapefile处理涉及到GIS编程,需要理解基本的GIS概念和特定库的用法。通过熟练掌握这些知识,你可以有效地在Java应用中处理和分析地理空间数据。

    Java大师级源码-tramaps-java:源代码-硕士论文

    【Java大师级源码-tramaps-java:源代码-硕士论文】这个项目是关于Java编程的一个高级研究,可能是一个硕士研究生级别的学术成果。这个源代码库,名为"tramaps-java-master",暗示了它可能是一个核心功能集或框架,...

    WiFi-positioning.rar_Java编程_Java_

    在本项目"WiFi-positioning.rar"中,我们探讨的是一个基于Java编程技术的室内WiFi定位系统。...通过阅读和理解这些源码,开发者不仅可以学习到WiFi定位系统的实现细节,还能深入掌握Java编程的各种技巧和最佳实践。

    JAVA 创建Shape文件。并在文件中添加一条折线

    在Java编程中,创建Shape文件并添加折线是一项常见的任务,尤其在图形用户界面(GUI)开发或GIS(地理信息系统)应用中。这篇博客“JAVA 创建Shape文件。并在文件中添加一条折线”可能详细解释了如何实现这个过程。...

    成为Java高手的25个学习目标.doc

    15. **J2EE技术**:掌握JNDI(Java命名和目录接口)、JMS(Java消息服务)、JTA/JTS(Java事务API/Java事务服务)、JMX(Java管理扩展)和JavaMail等技术。 通过逐步学习和实践这些目标,你可以逐步提升自己的Java...

    Java用的在线地图浏览模块.7z

    在Java编程领域,地图浏览模块通常涉及到地理信息系统(GIS)技术,它允许用户查看、分析和操作地理数据。"Java用的在线地图浏览模块.7z"可能包含了一个用于开发地图应用的Java库或者框架,这可能是开源项目,也可能...

    基于JEE在分布式环境下的底层结构(外文翻译+文献综述)毕业设计—(包含完整源码可运行).rar

    6. **JTA(Java Transaction API)** 和 **JTS(Java Transaction Service)**:支持分布式事务处理,确保在多个系统间的数据一致性。 7. **JCA(Java Connector Architecture)**:允许JEE应用与各种企业信息系统...

Global site tag (gtag.js) - Google Analytics