??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产精品无码久久九九大片 ,色婷五月综激情亚洲综合,无码乱人伦一区二区亚洲 http://m.tkk7.com/jnbzwm/articles/330552.htmlJava你我Java你我Wed, 01 Sep 2010 04:00:00 GMThttp://m.tkk7.com/jnbzwm/articles/330552.htmlhttp://m.tkk7.com/jnbzwm/comments/330552.htmlhttp://m.tkk7.com/jnbzwm/articles/330552.html#Feedback0http://m.tkk7.com/jnbzwm/comments/commentRss/330552.htmlhttp://m.tkk7.com/jnbzwm/services/trackbacks/330552.html关于try-catch-finally的用法我׃多说了。网上搜一下,资料很多?/span>

q里我想主要讨论下在finally块加?/span>return语句Q?strong>屏蔽异常的问题?/span>

我们先来看这样一D代码,


代码1Q?/span>

 1public class FinallyTest {   
 2    public static void main(String[] args) {   
 3        new FinallyTest().print();   
 4    }
   
 5    public void print() {   
 6        int i = -1;   
 7        try {   
 8            Thread.sleep(1);   
 9            i = 1 / 0;   
10        }
 catch (Exception e) {   
11            System.out.println("at catch block step 1.");   
12            throw e;   
13        }
 finally {   
14            System.out.println("at finally block i = " + i);   
15        }
   
16    }
   
17}


以上代码?/span>Eclipse里是不会~译通过的,因ؓ?/span>catch块中throw了一个异常,?/span>printҎq没有声明要抛出异常?/span>


现在我们修改代码Q让它能够通过~译Q代?/span>2Q?br />

1public class FinallyTest {   
2    public static void main(String[] args) throws Exception {   
3        new FinallyTest().print();   
4    }
   
5    public void print() throws Exception {   
6…  
7


是?/span>print?/span>mainҎ后加throws ExceptionQ然后运行,看运行结果:

1at catch block step 1.   
2at finally block i = -1  
3Exception in thread "main" java.lang.ArithmeticException: / by zero   
4    at wxhx.csdn2.FinallyTest.print(FinallyTest.java:12)   
5    at wxhx.csdn2.FinallyTest.main(FinallyTest.java:5)  

E序先是走到?/span>catch块的W一句,打印?/span>at catch block step 1.

但ƈ没有紧接着?/span>throw eQ?strong>x有立L个异?/span>Q之所以这栯Q是因ؓ异常的信息是?/span>finally块的打印信息之后才打印的?/span>

q个例子告诉我们Q?/span>finally不管?/span>?/span>异常与否Q?/span>都必?/span>?/span>?/span>行的?/span>?/span>?/span>Q如果中途终止了jvmQ就不必L行了Q?/span>

那么何时执行finally块中的代码呢Q?/span>

在这个例子中Q?/span>try块中有异常抛出,所?/span>finally块中的代?strong>是在执行?/span>catch语句之后、退出方法之前被执行?/span>(如果q里执行?/span>throw eQ则Ҏ退Z) ?/span>


 

下面再看另外一个代码,代码3Q?/span>

 1public class FinallyTest {   
 2    public static void main(String[] args) {   
 3        new FinallyTest().print();   
 4    }
   
 5    public void print() {   
 6        int i = -1;   
 7        try {   
 8            Thread.sleep(1);   
 9            i = 1 / 0;   
10        }
 catch (Exception e) {   
11            System.out.println("at catch block step 1.");   
12            throw e;   
13        }
 finally {   
14            System.out.println("at finally block i = " + i);   
15            return;   
16        }
   
17    }
   
18}
 


 

q段代码与之前相比,在finally块中增加了return语句?/p>

虽然在catch块中有throw e语句Q但在printҎ后ƈ不用声明throws ExceptionQ也可以通过~译?/p>

因ؓ在try块中有Thread.sleep(1);语句Q所以必要捕获InterruptedExceptionQ但在这U情况下Q即使我们把catch块去掉了Q也不会有问题,q是怎么回事呢?

因ؓ在finally块中的return语句屏蔽了异常?/p>

l过代码2我们已经知道了,异常在finally块被执行之前Q虽然会执行catch块中的代码,但ƈ不会退出方法,在退出方法之前,会{向finally块中执行Q而在finally块中又恰好有return语句Q所以方法就正常退ZQ在try块中产生的异常就不会有机会被抛出?/p>


----2009q?2?3?/p>



Java你我 2010-09-01 12:00 发表评论
]]>
析 Java Thread.join()http://m.tkk7.com/jnbzwm/articles/330549.htmlJava你我Java你我Wed, 01 Sep 2010 03:52:00 GMThttp://m.tkk7.com/jnbzwm/articles/330549.htmlhttp://m.tkk7.com/jnbzwm/comments/330549.htmlhttp://m.tkk7.com/jnbzwm/articles/330549.html#Feedback0http://m.tkk7.com/jnbzwm/comments/commentRss/330549.htmlhttp://m.tkk7.com/jnbzwm/services/trackbacks/330549.html阅读全文

Java你我 2010-09-01 11:52 发表评论
]]>
析java内存泄露问题http://m.tkk7.com/jnbzwm/articles/330538.htmlJava你我Java你我Wed, 01 Sep 2010 03:31:00 GMThttp://m.tkk7.com/jnbzwm/articles/330538.htmlhttp://m.tkk7.com/jnbzwm/comments/330538.htmlhttp://m.tkk7.com/jnbzwm/articles/330538.html#Feedback0http://m.tkk7.com/jnbzwm/comments/commentRss/330538.htmlhttp://m.tkk7.com/jnbzwm/services/trackbacks/330538.html最q一D|_在公叔R?/span>java内存泄露的问题进行了调查?/span>

问题的发玎ͼ

pȝ中在q箋不停地、反复进行一个操作(先打开AQ然后切替到画面BQ点ȝ面历再回到AQ如此反复)。经q长旉的测试,l常?/span>20时Q?/span>JVM的内存用量增长30M以上?/span>

 

问题的分析:

首先Ҏ操作Q找C执行的代码,对代码进行分析?/span>

Java会生内存泄露的原因Q经q本ơ调查,

1.对于打开?/span>socket{资源,没有做及时的回收处理?/span>
2.生存周期较长的对象,持有了生存周期较短的对象的引用,以至于那些生存周期短的对象,在无用的情况下,没有得到回收?br /> 3.对于cȝ成员变量为集合的情况Q对集合的用应该}慎。比如,一个专门保存用h作历的对象Q有全局变量List来保存用h有点击过的链接。但实际目中,不可能保存住用户的每一ơ链接操作,然后昄l用P有时候可能只是显C最新的20条。所以这时候就要对q个全局变量q行处理Q不能让它无限的膨胀下去?br /> 4.在类的成员变量ؓ集合的情况,集合中的元素又是比较复杂的对象,Q这个对象中可能q包含着是集合的成员变量Q在不需要此cȝ对象的时候,应该自己来实现对cȝ成员的销毁。如Q?br />
1Iterator itor = myMap.keySet().iterator();   
2while (itor.hasNext()) {   
3    MyObject selectedInfo = (MyObject) itor.next();   
4    selectedInfo.destroy();// 假设MyObject里有destroyҎQ对MyObjec中的成员q行销?nbsp;  
5    selectedInfo = null;   
6}
   
7myMap.clear();  

5.对单态模式应该慎用,?/span>?/span>?/span>象在被初始化后将?/span>JVM的整个生命周期中存在Q?/span>如果单?/span>?/span>象持有外?/span>?/span>象的引用Q那么这个外?/span>?/span>象将不能?/span>回收Q?/span>如故q个外部对象很庞大,那么对内存的消耗是很大的?br /> 6.虽然?/span>javaE序Q有GC帮助我们理内存Q但好的~程习惯q是需要的Q可以避免不必要的麻烦?/span>

虽然?/span>javaE序Q有GC帮助我们理内存Q但好的~程习惯q是需要的Q可以避免不必要的麻烦?/span>

1.复杂的对象,在不需要的情况下,最好能实现对它的成员的销毁,然后再将其赋?/span>null?br /> 2.对于打开的流Q一定要做及时的处理。另外对?/span>HttpURLConnection对象Q连接后Q要调用它的disconnectQ)Q不要对资源q行不必要的费?br /> 3.量用全局变量?br /> 4.在哪里生成对象,在哪里销毁它?/span>
5.量避免对象之间的相互引用?br />

最后,记述一下我记录内存的方法?/span>

׃对代码做好修改之后,要确认一下内存是否有明显增长?/span>

于是写一D代码,每个5分钟对对内存q行一ơ记录,在连l运?/span>20时候,做成曲线图,以便分析?/span>

Q以下是Z方便Q重新写的,原来目中用到的Q有一整套完备的定时器生成和v动的理c,q里没有写出来。)

 1import java.io.DataOutputStream;   
 2import java.io.FileOutputStream;   
 3import java.io.IOException;   
 4public class MemoryCollect {   
 5    public static void main(String args[]) {   
 6        MemoryCollector mc = new MemoryCollector(300000);   
 7        mc.start();   
 8    }
   
 9}
   
10class MemoryCollector extends java.util.TimerTask {   
11    private static final java.text.NumberFormat nf = java.text.NumberFormat   
12            .getPercentInstance();   
13    private static final java.text.DateFormat df = new java.text.SimpleDateFormat(   
14            "yyyy-MM-dd HH:mm:ss");   
15    private DataOutputStream dos = null;   
16    private long period = 0;   
17    private java.util.Timer timer = null;   
18    MemoryCollector(long p) {   
19        period = p;   
20        timer = new java.util.Timer();   
21    }
   
22    public void start() {   
23        timer.schedule(this0, period);   
24    }
   
25    public void run() {   
26        System.gc();   
27        Runtime imp = Runtime.getRuntime();   
28        imp.totalMemory();   
29        long totol = imp.totalMemory() / 1024;   
30        long free = imp.freeMemory() / 1024;   
31        try {   
32            dos = new DataOutputStream(new FileOutputStream("D:\\memory.txt",   
33                    true));   
34            String date = df.format(new java.util.Date());   
35            String info = date + "\t" + totol + "\t" + free + "\t"  
36                    + nf.format((double) free / (double) totol);   
37            System.out.println(info);   
38            dos.writeUTF(info + "\r");   
39            dos.flush();   
40            dos.close();   
41            dos = null;   
42        }
 catch (Exception e) {   
43            System.out.println(e);   
44        }
 finally {   
45            try {   
46                if (dos != null{   
47                    dos.flush();   
48                    dos.close();   
49                    dos = null;   
50                }
   
51            }
 catch (IOException e) {   
52                e.printStackTrace();   
53            }
   
54        }
   
55    }
   
56    public void stop() {   
57        super.cancel();   
58        if (timer != null{   
59            timer.cancel();   
60            timer = null;   
61        }
   
62    }
   
63}
 


----2009q?2?2?/span>


Java你我 2010-09-01 11:31 发表评论
]]>
[转]jdk与jre的区?/title><link>http://m.tkk7.com/jnbzwm/articles/330530.html</link><dc:creator>Java你我</dc:creator><author>Java你我</author><pubDate>Wed, 01 Sep 2010 03:11:00 GMT</pubDate><guid>http://m.tkk7.com/jnbzwm/articles/330530.html</guid><wfw:comment>http://m.tkk7.com/jnbzwm/comments/330530.html</wfw:comment><comments>http://m.tkk7.com/jnbzwm/articles/330530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/jnbzwm/comments/commentRss/330530.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/jnbzwm/services/trackbacks/330530.html</trackback:ping><description><![CDATA[<p>单的说JDK是面向开发h员用的SDKQ它提供了Java的开发环境和q行环境。SDK是Software Development Kit 一般指软g开发包Q可以包括函数库、编译程序等?br />     JDK是Java Development Kit<br /> JRE是Java Runtime Enviroment是指Java的运行环境,是面向JavaE序的用者,而不是开发者?/p> <p>如果安装了JDKQ会发现你的电脑有两套JREQ一套位?\jre 另外一套位?C:\Program Files\Java\j2re1.4.1_01 目录下,后面q套比前面那套少了Server端的Java虚拟机,不过直接前面那套的Server端Java虚拟机复制过来就行了。而且在安装JDK可以选择是否安装q个位于 C:\Program Files\Jav a 目录下的JRE。如果你只安装JREQ而不是JDKQ那么只会在 C:\Program Files\Java 目录下安装唯一的一套JRE?</p> <p>      JRE的地位就象一台PCZP我们写好的Win32应用E序需要操作系l帮我们q行Q同LQ我们编写的JavaE序也必要JRE才能q行。所以当你装完JDK后,如果分别在硬盘上的两个不同地方安装了两套JREQ那么你可以惌你的电脑有两台虚拟的Java PC机,都具有运行JavaE序的功能。所以我们可以说Q只要你的电脑安装了JREQ就可以正确q行Jav a应用E序?/p> <p>        1、ؓ什么Sun要让JDK安装两套相同的JREQ这是因为JDK里面有很多用Java所~写的开发工P如javac.exe、jar.exe{)Q而且都放|在 \lib\tools.jar 里。从下面例子可以看出Q先tools.jar改名为tools1.jarQ然后运行javac.exeQ显C如下结果: Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac /Main q个意思是_你输入javac.exe与输?java -cp c:\jdk\lib\tools.jar com.sun.tools.javac.Main 是一LQ会得到相同的结果。从q里我们可以证明javac.exe只是一个包装器QWrapperQ,而制作的目的是ؓ了让开发者免于输入太长的指命。而且可以发现\lib目录下的E序都很,不大? 9KQ从q里我们可以得出一个结论。就是JDK里的工具几乎是用Java所~写Q所以也是Java应用E序Q因此要使用JDK所附的工具来开发JavaE序Q也必须要自行附一套JRE才行Q所以位于C:\Program Files\Java目录下的那套JRE是用来q行一般JavaE序用的?</p> <p>       2、如果一台电脑安装两套以上的JREQ谁来决定呢Q这个重大Q务就落在java.exew上。Java.exe的工作就是找到合适的JRE来运行JavaE序?Java.exe依照底下的顺序来查找JREQ自q目录下有没有JREQ父目录有没有JREQ查询注册表Q?[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment] 所以java.exe的运行结果与你的电脑里面哪个JRE被执行有很大的关pR?</p> <p>      3、介lJVM JRE目录下的Bin目录有两个目录:server与client。这是真正的jvm.dll所在?jvm.dll无法单独工作Q当jvm.dll启动后,会用explicit的方法(是使用Win32 API之中的LoadLibrary()与GetProcAddress()来蝲入辅助用的动态链接库Q,而这些辅助用的动态链接库Q?dllQ都必须位于jvm.dll所在目录的父目录之中。因此想使用哪个JVMQ只需要设|PATHQ指向JRE所在目录底下的jvm.dll?/p> <p><br /> ----2008q?1?4?/p> <img src ="http://m.tkk7.com/jnbzwm/aggbug/330530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/jnbzwm/" target="_blank">Java你我</a> 2010-09-01 11:11 <a href="http://m.tkk7.com/jnbzwm/articles/330530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]java~译执行与jvm介绍http://m.tkk7.com/jnbzwm/articles/330527.htmlJava你我Java你我Wed, 01 Sep 2010 03:08:00 GMThttp://m.tkk7.com/jnbzwm/articles/330527.htmlhttp://m.tkk7.com/jnbzwm/comments/330527.htmlhttp://m.tkk7.com/jnbzwm/articles/330527.html#Feedback0http://m.tkk7.com/jnbzwm/comments/commentRss/330527.htmlhttp://m.tkk7.com/jnbzwm/services/trackbacks/330527.htmlJava虚拟?JVM)是可q行Java代码的假惌机。只要根据JVM规格描述解释器UL到特定的计算ZQ就能保证经q编译的MJava代码能够在该pȝ上运行。本文首先简要介l从Java文g的编译到最l执行的q程Q随后对JVM规格描述作一说明?br />   
  一.Java源文件的~译、下载、解释和执行
  Java应用E序的开发周期包括编译、下载、解释和执行几个部分。Java~译E序Java源程序翻译ؓJVM可执行代?字节码。这一~译q程同C/C++的编译有些不同。当C~译器编译生成一个对象的代码Ӟ该代码是为在某一特定gq_q行而生的。因此,在编译过E中Q编译程序通过查表所有对W号的引用{换ؓ特定的内存偏U量Q以保证E序q行。Java~译器却不将对变量和Ҏ的引用编译ؓ数值引用,也不定E序执行q程中的内存布局Q而是这些符号引用信息保留在字节码中Q由解释器在q行q程中创立内存布局Q然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可UL性和安全性?br />   
  q行JVM字节码的工作是由解释器来完成的。解释执行过E分三部q行Q代码的装入、代码的校验和代码的执行。装入代码的工作?c装载器"Qclass loaderQ完成。类装蝲器负责装入运行一个程序需要的所有代码,q也包括E序代码中的cLl承的类和被其调用的cR当c装载器装入一个类Ӟ该类被放在自q名字I间中。除了通过W号引用自己名字I间以外的类Q类之间没有其他办法可以影响其他cR在本台计算Z的所有类都在同一地址I间内,而所有从外部引进的类Q都有一个自q立的名字I间。这使得本地c通过׃n相同的名字空间获得较高的q行效率Q同时又保证它们与从外部引进的类不会怺影响。当装入了运行程序需要的所有类后,解释器便可确定整个可执行E序的内存布局。解释器为符号引用同特定的地址I间建立对应关系及查询表。通过在这一阶段定代码的内存布局QJava很好地解决了pcL变而子类崩溃的问题,同时也防止了代码对地址的非法访问?br />   
  随后Q被装入的代码由字节码校验器q行查。校验器可发现操作数栈溢出,非法数据cd转化{多U错误。通过校验后,代码便开始执行了?br />   
  Java字节码的执行有两U方式:
  1.x~译方式Q解释器先将字节码编译成机器码,然后再执行该机器码?br />   2.解释执行方式Q解释器通过每次解释q执行一段代码来完成Java字节码程 序的所有操作?br />   通常采用的是W二U方法。由于JVM规格描述h_的灵zL,q得将字节码翻译ؓ机器代码的工?br />   
  h较高的效率。对于那些对q行速度要求较高的应用程序,解释器可Java字节码即时编译ؓ机器码,从而很好地保证了Java代码的可UL性和高性能?br />   
  ?JVM规格描述
  JVM的设计目标是提供一个基于抽象规格描q的计算机模型,释程序开发h员提很好的灵zL,同时也确保Java代码可在W合该规范的Mpȝ上运行。JVM对其实现的某些方面给Z具体的定义,特别是对Java可执行代码,卛_节码(Bytecode)的格式给Z明确的规根{这一规格包括操作码和操作数的语法和数倹{标识符的数DC方式、以及JavacL件中的Java对象、常量缓冲池在JVM的存储映象。这些定义ؓJVM解释器开发h员提供了所需的信息和开发环境。Java的设计者希望给开发h员以随心所Ʋ用Java的自由?br />   
  JVM定义了控制Java代码解释执行和具体实现的五种规格Q它们是Q?br />   JVM指opȝ
  JVM寄存?br />   JVM栈结?br />   JVM片回收?br />   JVM存储?br />   
  2.1JVM指opȝ
  
  JVM指opȝ同其他计机的指令系l极其相伹{Java指o也是?操作码和操作C部分l成。操作码?位二q制敎ͼ操作数进紧随在操作码的后面,光度根据需要而不同。操作码用于指定一条指令操作的性质Q在q里我们采用汇编W号的Ş式进行说明)Q如iload表示从存储器中装入一个整敎ͼanewarray表示Z个新数组分配I间Qiand表示两个整数??Qret用于程控制Q表CZҎ一Ҏ的调用中q回。当长度大于8位时Q操作数被分Z个以上字节存放。JVM采用?big endian"的编码方式来处理q种情况Q即高位bits存放在低字节中。这?Motorola及其他的RISC CPU采用的编码方式是一致的Q而与Intel采用?little endian "的编码方式即低位bits存放在低位字节的Ҏ不同?br />   
  Java指opȝ是以Java语言的实Cؓ目的设计的,其中包含了用于调用方法和监视多先E系l的指o。Java?位操作码的长度得JVM最多有256U指令,目前已用了160多种操作码?br />   
  2.2JVM指opȝ
  
  所有的CPU均包含用于保存系l状态和处理器所需信息的寄存器l。如果虚拟机定义较多的寄存器Q便可以从中得到更多的信息而不必对栈或内存q行讉KQ这有利于提高运行速度。然而,如果虚拟Z的寄存器比实际CPU的寄存器多,在实现虚拟机时就会占用处理器大量的时间来用常规存储器模拟寄存器,q反而会降低虚拟机的效率。针对这U情况,JVM只设|了4个最为常用的寄存器。它们是Q?br />   pcE序计数?br />   optop操作数栈指?br />   frame当前执行环境指针
  vars指向当前执行环境中第一个局部变量的指针
  所有寄存器均ؓ32位。pc用于记录E序的执行。optop,frame和vars用于记录指向Java栈区的指针?br />   
  2.3JVM栈结?br />   
  作ؓZ栈结构的计算机,Java栈是JVM存储信息的主要方法。当JVM得到一个Java字节码应用程序后Q便代码中一个类的每一个方法创Z个栈框架Q以保存该方法的状态信息。每个栈框架包括以下三类信息Q?br />   局部变?br />   执行环境
  操作数栈
  
  局部变量用于存储一个类的方法中所用到的局部变量。vars寄存器指向该变量表中的第一个局部变量?br />   执行环境用于保存解释器对Java字节码进行解释过E中所需的信息。它们是Q上ơ调用的Ҏ、局部变量指针和操作数栈的栈和栈底指针。执行环境是一个执行一个方法的控制中心。例如:如果解释器要执行iadd(整数加法)Q首先要从frame寄存器中扑ֈ当前执行环境Q而后便从执行环境中找到操作数栈,从栈弹Z个整数进行加法运,最后将l果压入栈顶?br />   操作数栈用于存储q算所需操作数及q算的结果?br />   
  2.4JVM片回收?br />   
  Javacȝ实例所需的存储空间是在堆上分配的。解释器具体承担为类实例分配I间的工作。解释器在ؓ一个实例分配完存储I间后,便开始记录对该实例所占用的内存区域的使用。一旦对象用完毕,便将其回收到堆中?br />   在Java语言中,除了new语句外没有其他方法ؓ一对象甌和释攑ֆ存。对内存q行释放和回收的工作是由Javaq行pȝ承担的。这允许Javaq行pȝ的设计者自己决定碎片回收的Ҏ。在SUN公司开发的Java解释器和Hot Java环境中,片回收用后台线E的方式来执行。这不但行系l提供了良好的性能Q而且使程序设计h员摆׃自己控制内存使用的风险?br />   
  2.5JVM存储?br />   
  JVM有两cd储区Q常量缓冲池和方法区。常量缓冲池用于存储cdU、方法和字段名称以及串常量。方法区则用于存储JavaҎ的字节码。对于这两种存储区域具体实现方式在JVM规格中没有明规定。这使得Java应用E序的存储布局必须在运行过E中定Q依赖于具体q_的实现方式?br />   
  JVM是ؓJava字节码定义的一U独立于具体q_的规格描qͼ是Javaq_独立性的基础。目前的JVMq存在一些限制和不Q有待于q一步的完善Q但无论如何QJVM的思想是成功的?br />   
  Ҏ分析Q如果把Java原程序想象成我们的C++原程序,Java原程序编译后生成的字节码q当于C++原程序编译后?0x86的机器码Q二q制E序文gQ,JVM虚拟机相当于80x86计算机系l?Java解释器相当于80x86CPU。在80x86CPU上运行的是机器码Q在Java解释器上q行的是Java字节码?br />   
  Java解释器相当于q行Java字节码的“CPU”,但该“CPU”不是通过g实现的,而是用Y件实现的。Java解释器实际上是特定的^C的一个应用程序。只要实C特定q_下的解释器程序,Java字节码就能通过解释器程序在该^Cq行Q这是Java跨^台的Ҏ。当前,q不是在所有的q_下都有相应Java解释器程序,q也是Javaq不能在所有的q_下都能运行的原因Q它只能在已实现了Java解释器程序的q_下运行?br />



----2008q?1?7?/span>



Java你我 2010-09-01 11:08 发表评论
]]>
[转] java内存分配http://m.tkk7.com/jnbzwm/articles/java.htmlJava你我Java你我Wed, 01 Sep 2010 02:46:00 GMThttp://m.tkk7.com/jnbzwm/articles/java.htmlhttp://m.tkk7.com/jnbzwm/comments/330514.htmlhttp://m.tkk7.com/jnbzwm/articles/java.html#Feedback0http://m.tkk7.com/jnbzwm/comments/commentRss/330514.htmlhttp://m.tkk7.com/jnbzwm/services/trackbacks/330514.html在网上收集了一些关于java内存分配的知?br /> Java 中的堆和?/p>

单的_
Java把内存划分成两种Q一U是栈内存,一U是堆内存?

   在函C定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配?

   当在一D代码块定义一个变量时QJava在栈中个变量分配内存空_当超q变量的作用域后QJava会自动释放掉变量所分配的内存空_该内存空间可以立卌另作他用?

   堆内存用来存攄new创徏的对象和数组?

   在堆中分配的内存Q由Java虚拟机的自动垃圾回收器来理?

   在堆中生了一个数l或对象后,q可以在栈中定义一个特D的变量Q让栈中q个变量的取值等于数l或对象在堆内存中的首地址Q栈中的q个变量成了数l或对象的引用变量?

   引用变量q当于是ؓ数组或对象v的一个名Uͼ以后可以在E序中用栈中的引用变量来访问堆中的数组或对象?

 

        

具体的说Q?br /> 栈与堆都是Java用来在Ram中存放数据的地方。与C++不同QJava自动理栈和堆,E序员不能直接地讄栈或堆?
      Java的堆是一个运行时数据?cȝ(对象从中分配I间。这些对象通过new、newarray、anewarray和multianewarray{?指o建立Q它们不需要程序代码来昑ּ的释放。堆是由垃圾回收来负责的Q堆的优势是可以动态地分配内存大小Q生存期也不必事先告诉编译器Q因为它是在q行?动态分配内存的QJava的垃圾收集器会自动收走这些不再用的数据。但~点是,׃要在q行时动态分配内存,存取速度较慢?
      栈的优势是,存取速度比堆要快Q仅ơ于寄存器,栈数据可以共享。但~点是,存在栈中的数据大与生存期必L定的,~Z灉|性。栈中主要存放一些基?cd的变量(,int, short, long, byte, float, double, boolean, charQ和对象句柄?
      栈有一个很重要的特D性,是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3Q?
~译器先处理int a = 3Q首先它会在栈中创徏一个变量ؓa的引用,然后查找栈中是否?q个|如果没找刎ͼ将3存放q来Q然后将a指向3。接着处理int b = 3Q在创徏完b的引用变量后Q因为在栈中已经?q个|便将b直接指向3。这P出Ca与b同时均指?的情c这Ӟ如果再oa=4Q那么编译器 会重新搜索栈中是否有4|如果没有Q则?存放q来Qƈ令a指向4Q如果已l有了,则直接将a指向q个地址。因此a值的改变不会影响到b的倹{要注意q?U数据的׃n与两个对象的引用同时指向一个对象的q种׃n是不同的Q因U情况a的修改ƈ不会影响到b, 它是q译器完成的,它有利于节省I间。而一个对象引用变量修改了q个对象的内部状态,会媄响到另一个对象引用变量?

String是一个特D的包装cL据。可以用Q?
String str = new String("abc");
String str = "abc";
两种的Ş式来创徏Q第一U是用new()来新建对象的Q它会在存放于堆中。每调用一ơ就会创Z个新的对象?
而第二种是先在栈中创Z个对Stringcȝ对象引用变量strQ然后查找栈中有没有存放"abc"Q如果没有,则将"abc"存放q栈Qƈ令str指向”abc”Q如果已l有”abc” 则直接ostr指向“abc”?

          比较c里面的数值是否相{时Q用equals()ҎQ当试两个包装cȝ引用是否指向同一个对象时Q用==Q下面用例子说明上面的理论?
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一个对象的?

String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一ơ生成一个?
   因此用第二种方式创徏多个”abc”字符?在内存中其实只存在一个对象而已. q种写法有利与节省内存空? 同时它可以在一定程度上提高E序的运行速度Q因为JVM会自动根据栈中数据的实际情况来决定是否有必要创徏新对象。而对于String str = new String("abc")Q的代码Q则一概在堆中创徏新对象,而不其字符串值是否相{,是否有必要创建新对象Q从而加重了E序的负担?
   另一斚w, 要注? 我们在用诸如String str = "abc"Q的格式定义cLQL惛_然地认ؓQ创ZStringcȝ对象str。担心陷阱!对象可能q没有被创徏Q而可能只是指向一个先前已l创建的 对象。只有通过new()Ҏ才能保证每次都创Z个新的对象?׃Stringcȝimmutable性质Q当String变量需要经常变换其值时Q应该考虑使用StringBufferc,以提高程序效率?/p>

 


java中内存分配策略及堆和栈的比较
2.1 内存分配{略
按照~译原理的观?E序q行时的内存分配有三U策?分别是静态的,栈式?和堆式的.
静态存储分配是指在~译时就能确定每个数据目标在q行时刻的存储空间需?因而在~译时就可以l他们分配固定的内存I间.q种分配{略要求E序代码中不?许有可变数据l构(比如可变数组)的存?也不允许有嵌套或者递归的结构出?因ؓ它们都会D~译E序无法计算准确的存储空间需?
栈式存储分配也可UCؓ动态存储分?是由一个类g堆栈的运行栈来实现的.和静态存储分配相?在栈式存储方案中,E序Ҏ据区的需求在~译时是完全未知 ?只有到运行的时候才能够知道,但是规定在运行中q入一个程序模块时,必须知道该程序模块所需的数据区大小才能够ؓ其分配内?和我们在数据l构所熟知 的栈一?栈式存储分配按照先进后出的原则进行分配?
静态存储分配要求在~译时能知道所有变量的存储要求,栈式存储分配要求在过E的入口处必ȝ道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时 模块入口处都无法定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可利用块或I闲块组?堆中的内存可以按照Q意顺序分配和??

2.2 堆和栈的比较
上面的定义从~译原理的教材中ȝ而来,除静态存储分配之?都显得很呆板和难以理?下面撇开静态存储分?集中比较堆和?
从堆和栈的功能和作用来通俗的比?堆主要用来存攑֯象的Q栈主要是用来执行程序的.而这U不同又主要是由于堆和栈的特点决定的:
在编E中Q例如C/C++中,所有的Ҏ调用都是通过栈来q行?所有的局部变?形式参数都是从栈中分配内存空间的。实际上也不是什么分?只是从栈?向上用就?好像工厂中的传送带(conveyor belt)一?Stack Pointer会自动指引你到放东西的位|?你所要做的只是把东西放下来就?退出函数的时候,修改栈指针就可以把栈中的内容销?q样的模式速度最? 当然要用来运行程序了.需要注意的?在分配的时?比如Z个即要调用的程序模块分配数据区?应事先知道这个数据区的大?也就说是虽然分配是在E?序运行时q行?但是分配的大多是定?不变?而这?大小多少"是在~译时确定的,不是在运行时.
堆是应用E序在运行的时候请求操作系l分配给自己内存Q由于从操作pȝ理的内存分?所以在分配和销毁时都要占用旉Q因此用堆的效率非常?但是堆的 优点在于,~译器不必知道要从堆里分配多存储空_也不必知道存储的数据要在堆里停留多长的时?因此,用堆保存数据时会得到更大的灵zL。事实上,?向对象的多态?堆内存分配是必不可少?因ؓ多态变量所需的存储空间只有在q行时创Z对象之后才能定.在C++中,要求创徏一个对象时Q只需?new命o~制相关的代码即可。执行这些代码时Q会在堆里自动进行数据的保存.当然Qؓ辑ֈq种灉|性,必然会付Z定的代h:在堆里分配存储空间时会花 掉更长的旉Q这也正是导致我们刚才所说的效率低的原因,看来列宁同志说的?人的优点往往也是人的~点,人的~点往往也是人的优点(晕~).


2.3 JVM中的堆和?
JVM是基于堆栈的虚拟?JVM为每个新创徏的线E都分配一个堆?也就是说,对于一个JavaE序来说Q它的运行就是通过对堆栈的操作来完成的。堆栈以帧ؓ单位保存U程的状态。JVM对堆栈只q行两种操作:以为单位的压栈和出栈操作?
我们知道,某个U程正在执行的方法称为此U程的当前方?我们可能不知?当前Ҏ使用的UCؓ当前帧。当U程ȀzM个JavaҎ,JVM׃在线E的 Java堆栈里新压入一个。这个自然成ؓ了当前.在此Ҏ执行期间,q个帧将用来保存参数,局部变?中间计算q程和其他数?q个帧在q里和编?原理中的zdU录的概忉|差不多的.
从Java的这U分配机制来?堆栈又可以这L?堆栈(Stack)是操作系l在建立某个q程时或者线E?在支持多U程的操作系l中是线E?个线E徏立的存储区域Q该区域h先进后出的特性?
每一个Java应用都唯一对应一个JVM实例Q每一个实例唯一对应一个堆。应用程序在q行中所创徏的所有类实例或数l都攑֜q个堆中,q由应用所有的U程 ׃n.跟C/C++不同QJava中分配堆内存是自动初始化的。Java中所有对象的存储I间都是在堆中分配的Q但是这个对象的引用却是在堆栈中分配,?是说在建立一个对象时从两个地斚w分配内存Q在堆中分配的内存实际徏立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指?引用)而已?br /> 2.4 GC的思?br /> JavaZ么慢?JVM的存在当然是一个原?但有,在Java?除了单类?int,char{?的数据结?其它都是在堆中分配内?所以说Java的一切都是对?Q这也是E序慢的原因之一?br /> 我的x?应该说代表TIJ的观?,如果没有Garbage Collector(GC),上面的说法就是成立的.堆不象栈是连l的I间,没有办法指望堆本w的内存分配能够象堆栈一h有传送带般的速度,因ؓ,谁会 Z整理庞大的堆I间,让你几乎没有延迟的从堆中获取新的I间?
q个时?GC站出来解决问?我们都知道GC用来清除内存垃圾,为堆腑ևI间供程序?但GC同时也担负了另外一个重要的d,是要让Java中堆 的内存分配和其他语言中堆栈的内存分配一样快,因ؓ速度的问题几乎是众口一词的对Java的诟?要达到这L目的,必M堆的分配也能够做到象传送带 一?不用自己操心LI闲I间.q样,GC除了负责清除Garbage?q要负责整理堆中的对?把它们{Ud一个远Garbage的纯净I间中无 间隔的排列v?p堆栈中一L?q样Heap Pointer可以方便的指向传送带的v始位|?或者说一个未使用的空?Z一个需要分配内存的对象"指引方向".因此可以q样?垃圾攉影响了对 象的创徏速度,听v来很?对不?
那GC怎样在堆中找到所有存zȝ对象?前面说了,在徏立一个对象时Q在堆中分配实际建立q个对象的内?而在堆栈中分配一个指向这个堆对象的指???,那么只要在堆?也有可能在静态存储区)扑ֈq个引用,可以跟t到所有存zȝ对象.扑ֈ之后,GC它们从一个堆的块中移到另外一个堆的块?q?它们一个挨一个的排列h,p我们上面说的那样,模拟Z一个栈的结?但又不是先进后出的分?而是可以L分配?在速度可以保证的情况下, Isn't it great?
但是Q列宁同志说?人的优点往往也是人的~点,人的~点往往也是人的优点(再晕~~).GC()的运行要占用一个线E?q本w就是一个降低程序运行性能 的缺?更何况这个线E还要在堆中把内存翻来覆ȝ折腾.不仅如此,如上面所?堆中存活的对象被搬移了位|?那么所有对q些对象的引用都要重新赋?q?些开销都会D性能的降?


基础数据cd直接在栈I间分配Q方法的形式参数Q直接在栈空间分配,当方法调用完成后从栈I间回收。引用数据类型,需要用new来创建,既在栈空?分配一个地址I间Q又在堆I间分配对象的类变量 。方法的引用参数Q在栈空间分配一个地址I间Qƈ指向堆空间的对象区,当方法调用完成后从栈I间回收。局部变量new出来Ӟ在栈I间和堆I间中分配空 _当局部变量生命周期结束后Q栈I间立刻被回Ӟ堆空间区域等待GC回收。方法调用时传入的literal参数Q先在栈I间分配Q在Ҏ调用完成后从?I间分配。字W串帔R在DATA区域分配Qthis在堆I间分配。数l既在栈I间分配数组名称Q又在堆I间分配数组实际的大!

?对了Q补充一下static在DATA区域分配?/p>

其实是有规律的,只要你理解了q些个基本的原理Q?/p>

堆空间的话:操作pȝ有一个记录空闲内存地址的链表,当系l收到程序的甌Ӟ会遍历该链表Q寻扄一个空间大 于所甌I间的堆l点Q然后将该结点从I闲l点链表中删除,q将该结点的I间分配l程序。另外,对于大多数系l,会在q块内存I间中的首地址处记录本ơ分 配的大小Q这样代码中的delete语句才能正确的释放本内存I间。另外由于找到的堆结点的大小不一定正好等于申L大小Q系l会自动的将多余的那部分?新放入空闲链表中。是由new分配的内存,一般速度比较慢,而且Ҏ产生内存片Q不q用h最方便。另外,在WINDOWS下,最好的方式是用 VirtualAlloc分配内存Q他不是在堆Q也不是在栈是直接在q程的地址I间中保留一快内存,虽然用v来最不方ѝ但是速度快,也最灉|。是向高?址扩展的数据结构,是不q箋的内存区域。这是由于系l是用链表来存储的空闲内存地址的,自然是不q箋的,而链表的遍历方向是由低地址向高地址。堆的大受 限于计算机系l中有效的虚拟内存。由此可见,堆获得的I间比较灉|Q也比较大?/p>

栈空间的话:在Windows? 栈是向低地址扩展的数据结构,是一块连l的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是pȝ预先规定好的Q在WINDOWS下,栈的大小是固?的(是一个编译时q定的常数Q,如果甌的空间超q栈的剩余空间时Q将提示overflow。因此,能从栈获得的I间较小。只要栈的剩余空间大于所甌 I间Q系l将为程序提供内存,否则报异常提示栈溢出?ql自动分配,速度较快。但E序员是无法控制的?/p>

JVM中的堆和?/p>

JVM是基于堆栈的虚拟机。JVM为每个新创徏的线E都分配一个堆栈。也是_对于一个JavaE序来说Q它的运行就是通过对堆栈的操作来完成的。堆栈以帧ؓ单位保存U程的状态。JVM对堆栈只q行两种操作:以为单位的压栈和出栈操作?/p>

我们知道Q某个线E正在执行的ҎUCؓ此线E的当前Ҏ。我们可能不知道Q当前方法用的帧称为当前。当U程ȀzM个JavaҎQJVM׃?U程的Java堆栈里新压入一个。这个自然成ؓ了当前.在此Ҏ执行期间Q这个ឮ用来保存参敎ͼ局部变量,中间计算q程和其他数据。这个在这?和编译原理中的活动纪录的概念是差不多的?/p>

从Java的这U分配机制来?堆栈又可以这L解:堆栈(Stack)是操作系l在建立某个q程时或者线E?在支持多U程的操作系l中是线E?个线E徏立的存储区域Q该区域h先进后出的特性?/p>

每一个Java应用都唯一对应一个JVM实例Q每一个实例唯一对应一个堆。应用程序在q行中所创徏的所有类实例或数l都攑֜q个堆中Qƈ由应用所?的线E共享。跟C/C++不同QJava中分配堆内存是自动初始化的。Java中所有对象的存储I间都是在堆中分配的Q但是这个对象的引用却是在堆栈中??也就是说在徏立一个对象时从两个地斚w分配内存Q在堆中分配的内存实际徏立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指?引用)?巌Ӏ?/p>

 

----2008q?1?4?/p>

Java你我 2010-09-01 10:46 发表评论
]]>
վ֩ģ壺 Ʒר| ŮƵƵƵҳ| պ޹| Ůվ91ɫ| רȷӰ| ѿƸվƵ| 99þþþþѿ| ŮƵַ| ߹ۿwww³³| | avҹƷר| Ƶһ| 7x7x7x߹ۿ| avavavëƬ| vaĻþ| Ů18ëƬaëƬ| ɫվapp߹ۿ | 18ڵѹۿվ| ྫƷxxxx| ձһ߲| 114ëƬѹۿ| ѹۿ| Ƶ| AVרAVëվ | һѿ| avҹƷר| gvgvͬ| Ƶ߹ۿӰԺ| 99ƵƷƵ76| ޾ƷþþþþV| ޾Ʒ߹ۿ| Ʒ㽶˼һ | ձѲv| ڵֻˬվ| 㽶߹ۿ| 㽶Ƶ߹ۿ| ޳˸| ۲ӰԺѹۿ| 99ѹۿƵ| aƵѹۿ| ˾þùѹۿƵ|