ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲欧美日韩国产成人,日韩在线视精品在亚洲,亚洲成年人免费网站http://m.tkk7.com/gen-sky/category/40682.html勤æ€ã€è°}­a€ã€æ…Žè¡Œã€åŽš¿U¯ã€è–„å?/description>zh-cnThu, 28 Feb 2013 16:38:01 GMTThu, 28 Feb 2013 16:38:01 GMT60spring3 email å‘é€ä»£ç ?http://m.tkk7.com/gen-sky/articles/spring3_email.html星期äº?/dc:creator>星期äº?/author>Thu, 28 Feb 2013 10:08:00 GMThttp://m.tkk7.com/gen-sky/articles/spring3_email.htmlhttp://m.tkk7.com/gen-sky/comments/395869.htmlhttp://m.tkk7.com/gen-sky/articles/spring3_email.html#Feedback0http://m.tkk7.com/gen-sky/comments/commentRss/395869.htmlhttp://m.tkk7.com/gen-sky/services/trackbacks/395869.htmlé…置代ç éƒ½è¶…˜q‡äº†ä¸ÖM»£ç ?nbsp;
ä¸è¿‡é…置代ç éƒ½æ˜¯å¸¸ç”¨çš„,留ç€å¤‡ä†¾å§ã€?br />mavne pox é…ç½®



 1 <dependency>
 2             <groupId>javax.mail</groupId>
 3             <artifactId>mail</artifactId>
 4             <version>1.4</version>
 5         </dependency>
 6     <dependency>
 7             <groupId>org.springframework</groupId>
 8             <artifactId>spring-beans</artifactId>
 9             <version>${org.springframework.version}</version>
10         </dependency>

spring-xml é…ç½®
<bean id="propertyConfigurer"
        class
="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:cfg/config.properties</value>
            </list>
        </property>
    </bean>

    <bean id="mail"
        class
="org.springframework.mail.javamail.JavaMailSenderImpl">
        <!-- SMTPå‘é€é‚®ä»¶çš„æœåŠ¡å™¨çš„IP和端å?nbsp;-->
        <property name="host" value="${mail.host}" />
        <property name="port" value="${mail.port}" />

        <!-- ç™»é™†SMTPé‚®äšgå‘逿œåŠ¡å™¨çš„ç”¨æˆ·å和密ç ?nbsp;-->
        <property name="username" value="${mail.username}" />
        <property name="password" value="${mail.password}" />

        <!-- èŽ·å¾—é‚®äšg会è¯å±žæ€?验è¯ç™Õd½•é‚®äšgæœåŠ¡å™¨æ˜¯å¦æˆåŠ?/span>-->
        <property name="javaMailProperties">
            <props>
                <prop key="mail.smtp.auth">true</prop>
                <prop key="prop">true</prop>
                <prop key="mail.smtp.timeout">25000</prop>
            </props>
        </property>
    </bean>


properties æ–‡äšgé…ç½®

mail.host=smtp.yeah.net
mail.port=25
mail.username=****
mail.password=****
java ¾cÕdˆ†åˆ«äØ“åQ?br />
import org.springframework.context.support.AbstractApplicationContext;

import com.ms.AppContext;

public class SpringHelper {

    /**
     * èŽ·å–springä¾èµ–注入的对è±?br />     * 
     * 
@param name
     * 
@return Object Bean
     
*/
    public static Object getBean(String name) {
        AbstractApplicationContext ctx = AppContext.getInstance()
                .getAppContext();

        return ctx.getBean(name);
    }
}


import java.util.ArrayList;
import java.util.List;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppContext {
    private static AppContext instance;

    private volatile AbstractApplicationContext appContext;

    public synchronized static AppContext getInstance() {
        if (instance == null) {
            instance = new AppContext();
        }

        return instance;
    }

    private AppContext() {
        List<String> list = new ArrayList<String>();
        list.add("/cfg/*.xml");

        String ss[] = list.toArray(new String[] {});
        for (int i = 0; i < ss.length; i++) {
            System.out.println("ss[" + i + "]" + ss[i]);

        }

        this.appContext = new ClassPathXmlApplicationContext(ss);
    }

    public AbstractApplicationContext getAppContext() {
        return appContext;
    }
}



import java.io.File;
import java.util.Date;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import com.ms.SpringHelper;
import com.util.Configuration;

/**
 * å‘é€é‚®ä»?nbsp;工具
 * 
 * 
@author 
 * @file com.ms.util --- SentMaileUtil.java
 * 
@version 2013-2-28 -下åˆ03:42:03
 
*/
public class SendMaileUtil {
    private static JavaMailSender javaMailSender;

    private static Logger logger = Logger.getLogger(SendMaileUtil.class);

    private static JavaMailSender newIntstance() {
        if (javaMailSender == null) {
            javaMailSender = (JavaMailSender) SpringHelper.getBean("mail");
        }
        return javaMailSender;
    }

    /**
     * å‘é€çš„æ–‡æœ¬‹¹‹è¯•é‚®äšg
     * 
     * 
@param to
     * 
@param mailSubject
     * 
@param mailBody
     
*/
    public static void sendTextMaile(String to, String mailSubject,
            String mailBody) {
        if (logger.isDebugEnabled())
            logger.debug("准备å‘逿–‡æœ¬åÅžå¼çš„é‚®äšg");
        SimpleMailMessage mail1 = new SimpleMailMessage();
        String from = Configuration.getValue("mail.form");
        mail1.setFrom(from);// å‘é€ähå片
        mail1.setTo(to);// æ”¶äšg人邮½Ž?/span>
        mail1.setSubject(mailSubject);// é‚®äšg主题
        mail1.setSentDate(new Date());// é‚®äšgå‘逿—¶é—?/span>
        mail1.setText(mailBody);

        // ¾Ÿ¤å‘
        SimpleMailMessage[] mailMessages = { mail1 };
        newIntstance().send(mailMessages);

        if (logger.isDebugEnabled())
            logger.debug("文本形å¼çš„邮件å‘逿ˆåŠŸï¼åQï¼");
    }

    /**
     * ä»?nbsp;HTML脚本形å¼é‚®äšgå‘é€?br />     * 
     * 
@param to
     * 
@param mailSubject
     * 
@param mailBody
     
*/
    public static void sendHtmlMail(String to, String mailSubject,
            String mailBody) {
        JavaMailSender mailSender = newIntstance();
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        try {
            if (logger.isDebugEnabled())
                logger.debug("HTML脚本形å¼é‚®äšg正在å‘é€?img src="http://m.tkk7.com/Images/dot.gif" alt="" />");
            // è®„¡½®utf-8或GBK¾~–ç åQŒå¦åˆ™é‚®ä»¶ä¼šæœ‰äØ•ç ?/span>
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true,
                    "UTF-8");
            // è®„¡½®å‘é€ähå片
            String from = Configuration.getValue("mail.form");
            helper.setFrom(from);
            // è®„¡½®æ”¶äšg人å片和地å€
            helper.setTo(new InternetAddress("\""
                    + MimeUtility.encodeText("gamil邮箱") + "\" <" + to + ">"));// å‘é€è€?br />            // é‚®äšgå‘逿—¶é—?/span>
            helper.setSentDate(new Date());
            // è®„¡½®å›žå¤åœ°å€
            helper.setReplyTo(new InternetAddress(from));
            // è®„¡½®æŠ„é€çš„å片和地å€
            
// helper.setCc(InternetAddress.parse(MimeUtility.encodeText("抄é€äh001")
            
// + " <@163.com>," + MimeUtility.encodeText("抄é€äh002")
            
// + " <@foxmail.com>"));
            
// ä¸»é¢˜
            helper.setSubject("Ýž”피언쉽");
            // é‚®äšg内容åQŒæ³¨æ„åŠ å‚æ•°trueåQŒè¡¨½Cºå¯ç”¨htmlæ ¼å¼
            helper
                    .setText(
                            "<html><head></head><body><h1>hello!!我是乔布æ–?lt;/h1></body></html>",
                            true);
            // å‘é€?/span>
            mailSender.send(mimeMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (logger.isDebugEnabled())
            logger.debug("HTML脚本形å¼é‚®äšgå‘逿ˆåŠŸï¼åQï¼");
    }

    /**
     * ä»¥é™„件的形å¼å‘é€é‚®ä»?br />     * 
     * 
@param to
     *            æ”¶äšg人eamil åœ°å€
     * 
@param toName
     *            æ”¶äšg人昵¿U?br />     * 
@param mailSubject
     *            ä¸»é¢˜
     * 
@param mailBody
     *            å†…容ä½?br />     * 
@param files
     *            é™„äšg
     
*/
    public static void sendFileMail(String to, String toName,
            String mailSubject, String mailBody, File[] files) {
        JavaMailSender mailSender = newIntstance();
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        try {
            if (logger.isDebugEnabled())
                logger.debug("带附件和囄¡‰‡çš„邮件正在å‘é€?img src="http://m.tkk7.com/Images/dot.gif" alt="" />");

            // è®„¡½®utf-8或GBK¾~–ç åQŒå¦åˆ™é‚®ä»¶ä¼šæœ‰äØ•ç ?/span>
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true,
                    "UTF-8");
            // è®„¡½®å‘é€ähå片
            String from = Configuration.getValue("mail.form");
            helper.setFrom(from);

            // è®„¡½®æ”¶äšg人邮½Ž?/span>
            helper.setTo(new InternetAddress("\""
                    + MimeUtility.encodeText(toName) + "\" <" + to + ">"));

            // è®„¡½®å›žå¤åœ°å€
            
// helper.setReplyTo(new InternetAddress("@qq.com"));

            
// è®„¡½®æ”¶äšg人抄é€çš„å片和地å€(相当于群å‘了)
            
// helper.setCc(InternetAddress.parse(MimeUtility.encodeText("邮箱001")
            
// + " <@163.com>," + MimeUtility.encodeText("邮箱002")
            
// + " <@foxmail.com>"));

            
// ä¸»é¢˜
            helper.setSubject(mailSubject);
            // é‚®äšg内容åQŒæ³¨æ„åŠ å‚æ•°trueåQŒè¡¨½Cºå¯ç”¨htmlæ ¼å¼
            helper.setText(mailBody);
            if (files != null && files.length > 0) {
                for (int i = 0; i < files.length; i++)
                    // åР入附äšg
                    helper.addAttachment(MimeUtility.encodeText(files[i]
                            .getName()), files[i]);
            }
            // åŠ å…¥æ’图
            helper.addInline(MimeUtility.encodeText("pic01"), new File(
                    "c:/temp/2dd24be463.jpg"));
            // å‘é€?/span>
            mailSender.send(mimeMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (logger.isDebugEnabled()) {
            logger.debug("带附件和囄¡‰‡çš„邮件å‘逿ˆåŠŸï¼åQï¼");
        }
    }

    public static void main(String[] args) {
        PropertyConfigurator.configure(ClassLoader
                .getSystemResource("cfg/log4j.properties"));

        SendMaileUtil.sendTextMaile("*****@gmail.com",
                "Spring Mail ‹¹‹è¯•é‚®äšg", "Hello,Boy,This is my Spring Mail,哈哈åQï¼");

        SendMaileUtil.sendHtmlMail("*****@gmail.com", nullnull);
        File file = new File("c:/temp");
        File[] fs = file.listFiles();

        SendMaileUtil.sendFileMail("******@yeah.net", "æ˜ëЧ°", "主题", "内容",
                fs);

    }
}









import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import com.pub.Forward;

/**
 * è¯Õd–propertiesæ–‡äšg
 * 
@author 
 *
 
*/
public class Configuration
{
    private static Properties propertie;
    private InputStream in;
    private static Configuration config = new Configuration();
    
    /**
     * åˆå§‹åŒ–Configuration¾c?br />     
*/
    public Configuration()
    {
        propertie = new Properties();
        try {
//            System.out.println(System.getProperty("user.dir"));
//            inputFile = new FileInputStream("cfg/config.properties");
            in =  ClassLoader.getSystemResourceAsStream("cfg/config.properties");
            propertie.load(in);
            in.close();
        } catch (FileNotFoundException ex) {
            System.out.println("è¯Õd–属性文ä»?-->å¤ÞpÓ|åQ? åŽŸå› åQ𿖇件èµ\径错误或者文件ä¸å­˜åœ¨");
            ex.printStackTrace();
        } catch (IOException ex) {
            System.out.println("è£…è²æ–‡äšg--->å¤ÞpÓ|!");
            ex.printStackTrace();
        }        
    }
    

    
    /**
     * é‡è²å‡½æ•°åQŒå¾—到keyçš„å€?br />     * 
@param key å–得其值的é”?br />     * @return keyçš„å€?br />     */
    public static  String getValue(String key)
    {
        if(propertie.containsKey(key)){
            String value = propertie.getProperty(key);//得到æŸä¸€å±žæ€§çš„å€?/span>
            return value;
        }
        else 
            return "";
    }//end getValue()

    


    
    public static void main(String[] args)
    {

        System.out.println(Configuration.getValue("aaa"));
        System.out.println(System.getProperty("user.dir"));


        
    }//end main()
    
}//end class ReadConfigInfo





























]]>
ã€æ‰¾é”™é¢˜ã€?出除list集åˆä¸­çš„æ•°å­—http://m.tkk7.com/gen-sky/articles/list.html星期äº?/dc:creator>星期äº?/author>Thu, 17 Jun 2010 07:36:00 GMThttp://m.tkk7.com/gen-sky/articles/list.htmlhttp://m.tkk7.com/gen-sky/comments/323722.htmlhttp://m.tkk7.com/gen-sky/articles/list.html#Feedback0http://m.tkk7.com/gen-sky/comments/commentRss/323722.htmlhttp://m.tkk7.com/gen-sky/services/trackbacks/323722.html 1     public static void main(String[] args) {
 2         List<String> list = new ArrayList<String>();
 3         list.add("a");
 4         list.add("b");
 5         list.add("c");
 6         list.add("136");
 7         list.add("14");
 8         list.add("f");
 9         
10         for(int i = 0;i<list.size();i++){
11             String str = list.get(i);
12             if(isNumeric(str)){
13                 list.remove(i);
14             }
15         }
16         for(int i = 0;i<list.size();i++){
17             System.out.println(list.get(i));
18         }
19     }
20     public static boolean isNumeric(String str) { // åˆ¤æ–­å­—符串是å¦äؓ数字
21         Pattern pattern = Pattern.compile("[0-9]*");
22         Matcher isNum = pattern.matcher(str);
23         if (!isNum.matches()) {
24             return false;
25         }
26         return true;
27     }

]]>
[转] 垃圾攉™›†­‘£å²(Garbage Collection )http://m.tkk7.com/gen-sky/articles/GarbageCollection.html星期äº?/dc:creator>星期äº?/author>Thu, 03 Dec 2009 06:56:00 GMThttp://m.tkk7.com/gen-sky/articles/GarbageCollection.htmlhttp://m.tkk7.com/gen-sky/comments/304621.htmlhttp://m.tkk7.com/gen-sky/articles/GarbageCollection.html#Feedback0http://m.tkk7.com/gen-sky/comments/commentRss/304621.htmlhttp://m.tkk7.com/gen-sky/services/trackbacks/304621.html

垃圾攉™›†­‘£å²

本文å‘表äº?004òq?月《CSDNå¼€å‘高手ã€?/p>

写作本文的åˆè¡äh˜¯æƒ›_’Œå¤§å®¶åˆ†äín垃圾攉™›†åQ?Garbage Collection åQ‰æŠ€æœ¯ç®€å•而有­‘£çš„å‘展åŒÓ€‚动½W”之å‰ï¼Œæˆ‘站在窗边,望了望正在å°åŒºé‡Œè£…è¿åžƒåœ¾çš„æ¸…‹zèžR。和生活中环å«å·¥äºÞZ»¬æ¸…è¿åžƒåœ¾çš„工作相ä¼û|¼Œè½¯äšgå¼€å‘里的垃圾收集其å®? ž®±æ˜¯ä¸€¿U自动打扫和清除内存垃圾的技术,它å¯ä»¥æœ‰æ•ˆé˜²èŒƒåЍæ€å†…存分é…中å¯èƒ½å‘生的两个å±é™©ï¼šå› å†…存垃圾过多而引å‘的内存耗尽åQˆè¿™å’Œç”Ÿ‹zÕdžƒåœ‘Ö µå¡žæŽ’污管é“çš„ å±é™©òq¶æ²¡æœ‰ä»€ä¹ˆæœ¬è´¨çš„ä¸åŒåQ‰ï¼Œä»¥åŠä¸æ°å½“的内存释放所造æˆçš„å†…å­˜éžæ³•引用(˜q™ç±»ä¼égºŽæˆ‘们在生‹zÖM¸­ä¹°åˆ°äº†ä¸€ç“¶å·²¾l过期三òq´çš„牛奶åQ‰ã€?

æ®åކå²å­¦å®¶ä»¬ä»‹ç»åQŒå››åƒå¤šòq´å‰çš„å¤åŸƒåŠäººå·²¾l在城市里å¾è®¾äº†å®Œå–„的排污和垃圾清è¿è®¾æ–½åQŒä¸€åƒå¤šòq´å‰çš„中国ähæ›´æ˜¯ä¿®ç­‘äº†å½“æ—¶ä¸–ç•Œä¸Šä¿æ´èƒ½åŠ›æœ€å¼ºçš„éƒ½å¸‚ ——长安。今天,当我们在软äšgå¼€å‘中体验自动垃圾攉™›†çš„便æ·ä¸Žèˆ’适时åQŒæˆ‘们至ž®‘应当知é“,˜q™ç§æ‹’ç»æ‚䨕ã€è¿½æ±‚æ•´‹zçš„“垃圾攉™›†”¾_„¡¥žå…¶å®žæ˜¯äh¾c»è‡ªå¤ä»¥æ¥å°± å·²ç»å…·å¤‡äº†çš„ã€?

æ‹“è’æ—¶ä»£

国内的程åºå‘˜å¤§å¤šæ˜¯åœ¨ Java 语言中第一‹Æ¡æ„Ÿå—到垃圾攉™›†æŠ€æœ¯çš„巨大™ì…力的,许多äºÞZ¹Ÿå› æ­¤æŠ?Java 和垃圾收集看æˆäº†å¯†ä¸å¯åˆ†çš„æ•´ä½“。但事实上,垃圾攉™›†æŠ€æœ¯æ—©åœ?Java 语言问世å‰?30 多年ž®±å·²¾lå‘展和æˆç†Ÿèµäh¥äº†ï¼Œ Java 语言所åšçš„ä¸è¿‡æ˜¯æŠŠ˜q™é¡¹¼œžå¥‡çš„æŠ€æœ¯å¸¦åˆîCº†òq¿å¤§½E‹åºå‘˜èín边而已ã€?

如果一定è¦ä¸ºåžƒåœ¾æ”¶é›†æŠ€æœ¯æ‰¾ä¸€ä¸ªå­ªç”Ÿå…„弟,那么åQ?Lisp è¯­è¨€æ‰æ˜¯å½“之无愧的äh选ã€?1960 òq´å‰åŽè¯žç”ŸäºŽ MIT çš?Lisp 语言是第一¿U高度ä¾èµ–于动æ€å†…å­˜åˆ†é…æŠ€æœ¯çš„è¯­è¨€åQ?Lisp 中几乎所有数æ®éƒ½ä»?#8220;è¡?#8221;çš„åÅžå¼å‡ºçŽŽÍ¼Œè€?#8220;è¡?#8221;所å ç”¨çš„空间则是在堆中动æ€åˆ†é…得到的ã€? Lisp 语言先天ž®±å…·æœ‰çš„动æ€å†…存管ç†ç‰¹æ€§è¦æ±?Lisp 语言的设计者必™å»è§£å†›_ †ä¸­æ¯ä¸€ä¸ªå†…å­˜å—的自动释æ”ùN—®é¢˜ï¼ˆå¦åˆ™åQ?Lisp ½E‹åºå‘˜å°±å¿…然被程åºä¸­ä¸è®¡å…¶æ•°çš?free æˆ?delete è¯­å¥æ·Ò޲¡åQ‰ï¼Œ˜q™ç›´æŽ¥å¯¼è‡´äº†åžƒåœ¾æ”‰™›†æŠ€æœ¯çš„诞生和å‘展——说å¥é¢˜å¤–è¯åQŒä¸Šå¤§å­¦æ—Óž¼Œä¸€ä½è€å¸ˆæ›‘Ö‘Šè¯‰æˆ‘们, Lisp 是对çŽîC»£è½¯äšgå¼€å‘æŠ€æœ¯èµA献最大的语言。我当时对这一说法ä¸ä»¥ä¸ºç„¶åQšå¸ƒæ»¡äº†åœ†æ‹¬åøP¼Œçœ‹ä¸ŠåŽÕdƒ˜q·å®«ä¸€æ ïLš„ Lisp 语言怎么能比 C 语言æˆ? Pascal 语言更伟大呢åQŸä¸˜q‡çŽ°åœ¨ï¼Œå½“æˆ‘çŸ¥é“垃圾攉™›†æŠ€æœ¯ã€æ•°æ®ç»“构技术ã€äh工智能技术ã€åÆˆè¡Œå¤„ç†æŠ€æœ¯ã€è™šæ‹ŸæœºæŠ€æœ¯ã€å…ƒæ•°æ®æŠ€æœ¯ä»¥åŠç¨‹åºå‘˜ä»¬è€³ç†Ÿèƒ½è¯¦çš„许多技术都èµ? æºäºŽ Lisp 语言æ—Óž¼Œæˆ‘特别想å‘é‚£ä½è€å¸ˆå½“é¢é“æ­‰åQŒåƈ收回我当时的òq¼ç¨šæƒÏx³•ã€?

知é“äº?Lisp 语言与垃圾收集的密切关系åQŒæˆ‘们就ä¸éš¾ç†è§£åQŒäؓ什么垃圾收集技术的两ä½å…ˆé©±è€?J. McCarthy å’?M. L. Minsky åŒæ—¶ä¹Ÿæ˜¯ Lisp 语言å‘展å²ä¸Šçš„é‡è¦äh物了ã€?J. McCarthy æ˜?Lisp 之父åQŒä»–åœ¨å‘æ˜?Lisp è¯­è¨€çš„åŒæ—¶ä¹Ÿ½W¬ä¸€‹Æ¡å®Œæ•´åœ°æè¿°äº†åžƒåœ¾æ”¶é›†çš„½Ž—法和实现方å¼ï¼› M. L. Minsky 则在å‘展 Lisp 语言的过½E‹ä¸­æˆäؓ了今天好几ç§ä¸ÀLµåžƒåœ¾æ”‰™›†½Ž—法的奠åŸÞZh——和当时ä¸å°‘技术大师的¾låŽ†ç›æ€¼¼åQ?J. McCarthy å’?M. L. Minsky 在许多ä¸åŒçš„æŠ€æœ¯é¢†åŸŸé‡Œéƒ½å–得了令äh艳ç±M的戞®±ã€‚也许,åœ?1960 òq´ä»£é‚£ä¸ªè½¯äšgå¼€å‘å²ä¸Šçš„æ‹“è’æ—¶ä»£é‡Œï¼Œæ€ç»´æ•æ·ã€æ„å¿—åšå®šçš„研究者更å®ÒŽ˜“æˆäؓ无所ä¸èƒ½çš„西部硬汉å§ã€?

在了解垃圾收集算法的èµähºä¹‹å‰åQŒæœ‰å¿…è¦å…ˆå›ž™å¾ä¸€ä¸‹å†…存分é…çš„ä¸»è¦æ–¹å¼ã€‚我们知é“,大多æ•îC¸»‹¹çš„语言或è¿è¡ŒçŽ¯å¢ƒéƒ½æ”¯æŒä¸‰ç§æœ€åŸºæœ¬çš„å†…å­˜åˆ†é…æ–¹å¼ï¼Œå®ƒä»¬åˆ†åˆ«æ˜¯ï¼š

一ã€é™æ€åˆ†é…( Static Allocation åQ‰ï¼šé™æ€å˜é‡å’Œå…¨å±€å˜é‡çš„分é…åÅžå¼ã€‚我们å¯ä»¥æŠŠé™æ€åˆ†é…çš„å†…å­˜çœ‹æˆæ˜¯å®¶é‡Œçš„è€ç”¨å®¶å…·ã€‚通常åQŒå®ƒä»¬æ— éœ€é‡Šæ”¾å’Œå›žæ”Óž¼Œå› äؓ没äh会天天把大衣柜当作垃圾扔到窗外ã€?

二ã€è‡ªåŠ¨åˆ†é…( Automatic Allocation åQ‰ï¼šåœ¨æ ˆä¸­äؓ局部å˜é‡åˆ†é…内存的æ–ÒŽ³•。栈中的内存å¯ä»¥éšç€ä»£ç å—退出时的出栈æ“作被自动释放。这¾cÖM¼¼äºŽåˆ°å®¶ä¸­ä¸²é—¨çš„访客,天色一晚就è¦å„回å„å®Óž¼Œé™¤äº†ä¸ªåˆ« ä¸è¯†æ—¶åŠ¡è€…ä»¥å¤–ï¼Œæˆ‘ä»¬ä¸€èˆ¬æ²¡å¿…è¦æŠŠå®¢äººæ†åœ¨åžƒåœ¾è¢‹é‡Œæ‰«åœ°å‡ºé—¨ã€?

三ã€åЍæ€åˆ†é…( Dynamic Allocation åQ‰ï¼šåœ¨å †ä¸­åЍæ€åˆ†é…内存空间以存储数æ®çš„æ–¹å¼ã€‚堆中的内存å—å¥½åƒæˆ‘ä»¬æ—¥å¸æ€‹É用的˜¡å·¾¾U¸ï¼Œç”¨è¿‡äº†å°±å¾—扔到垃圄¡®±é‡Œï¼Œå¦åˆ™å±‹å†…ž®×ƒ¼šæ»¡åœ°ç‹ÆD—‰ã€‚åƒæˆ‘è¿™æ ïLš„æ‡’ähå? 梦都æƒÏxœ‰ä¸€å°å®¶ç”¨æœºå™¨äh跟在íw«è¾¹æ‰“扫å«ç”Ÿã€‚在软äšgå¼€å‘中åQŒå¦‚果你懒得释放内存åQŒé‚£ä¹ˆä½ ä¹Ÿéœ€è¦ä¸€å°ç±»ä¼¼çš„æœºå™¨äººâ€”—这其实ž®±æ˜¯ä¸€ä¸ªç”±ç‰¹å®š½Ž—法实现的垃圾收é›? 器ã€?

也就是说åQŒä¸‹é¢æåˆ°çš„æ‰€æœ‰åžƒåœ¾æ”¶é›†ç®—法都是在½E‹åº˜q行˜q‡ç¨‹ä¸­æ”¶é›†åƈ清ç†åºŸæ—§“˜¡å·¾¾U?#8221;的算法,它们的æ“ä½œå¯¹è±¡æ—¢ä¸æ˜¯é™æ€å˜é‡ï¼Œä¹Ÿä¸æ˜¯å±€éƒ¨å˜é‡ï¼Œè€Œæ˜¯å †ä¸­æ‰€æœ‰å·²åˆ†é…内存å—ã€?

引用计数åQ?Reference Counting åQ‰ç®—æ³?/h3>

1960 òq´ä»¥å‰ï¼ŒäºÞZ»¬ä¸ø™ƒšèƒŽä¸­çš?Lisp 语言设计垃圾攉™›†æœºåˆ¶æ—Óž¼Œ½W¬ä¸€ä¸ªæƒ³åˆ°çš„½Ž—法是引用计数算法。拿˜¡å·¾¾U¸çš„例孿¥è¯´åQŒè¿™¿U算法的原ç†å¤§è‡´å¯ä»¥æè¿°ä¸ºï¼š

åˆé¤æ—Óž¼Œä¸ÞZº†æŠŠè„‘å­é‡Œ½Hç„¶è·›_‡ºæ¥çš„设计ç‰|„Ÿè®îC¸‹æ¥ï¼Œæˆ‘从˜¡å·¾¾U¸è¢‹ä¸­æŠ½å‡ÞZ¸€å¼ é¤å·„¡º¸åQŒæ‰“½Ž—在上é¢ç”Õd‡º¾pÈ»Ÿæž¶æž„çš„è“图。按ç…?#8220;˜¡å·¾¾U怋É用规¾U¦ä¹‹å¼•用计数 ç‰?#8221;çš„è¦æ±‚,ç”Õd›¾ä¹‹å‰åQŒæˆ‘必须先在˜¡å·¾¾U¸çš„一角写上计数å€?1 åQŒä»¥è¡¨ç¤ºæˆ‘在使用˜q™å¼ ˜¡å·¾¾U¸ã€‚è¿™æ—Óž¼Œå¦‚果你也想看看我ç”Èš„è“图åQŒé‚£ä½ å°±è¦æŠŠ˜¡å·¾¾U怸Šçš„计数值加 1 åQŒå°†å®ƒæ”¹ä¸?2 åQŒè¿™è¡¨æ˜Žç›®å‰æœ?2 个ähåœ¨åŒæ—¶ä‹É用这张é¤å·„¡º¸åQˆå½“ç„Óž¼Œæˆ‘是ä¸ä¼šå…许你用˜q™å¼ ˜¡å·¾¾U¸æ¥æ“¦éËEæ¶•çš„åQ‰ã€‚你看完åŽï¼Œå¿…é¡»æŠŠè®¡æ•°å€¼å‡ 1 åQŒè¡¨æ˜Žä½ å¯¹è¯¥˜¡å·¾¾U¸çš„使用已绾l“æŸã€‚åŒæ øP¼Œå½“我ž®†é¤å·„¡º¸ä¸Šçš„内容全部誊写到笔记本上之åŽï¼Œæˆ‘也会自觉地把é¤å·„¡º¸ä¸Šçš„è®¡æ•°å€¼å‡ 1 。此æ—Óž¼Œä¸å‡ºæ„外的è¯åQŒè¿™å¼ é¤å·„¡º¸ä¸Šçš„计数值应当是 0 åQŒå®ƒä¼šè¢«åžƒåœ¾æ”‰™›†å™¨â€”—å‡è®ùN‚£æ˜¯ä¸€ä¸ªä¸“门负责打扫å«ç”Ÿçš„æœºå™¨äººâ€”—æ¡èµäh¥æ‰”到垃圾½Ž±é‡ŒåQŒå› ä¸ºåžƒåœ¾æ”¶é›†å™¨çš„æƒŸä¸€ä½¿å‘½ž®±æ˜¯æ‰‘Öˆ°æ‰€æœ‰è®¡æ•°å€égØ“ 0 çš„é¤å·„¡º¸òq¶æ¸…ç†å®ƒä»¬ã€?

引用计数½Ž—法的优点和¾~ºé™·åŒæ ·æ˜Žæ˜¾ã€‚这一½Ž—法在执行垃圾收集ä“Q务时速度较快åQŒä½†½Ž—法对程åºä¸­æ¯ä¸€‹Æ¡å†…存分é…和指针æ“作æå‡ºäº†é¢å¤–çš„è¦æ±‚åQˆå¢žåŠ æˆ–å‡å°‘ 内存å—的引用计数åQ‰ã€‚æ›´é‡è¦çš„æ˜¯åQŒå¼•用计数算法无法正¼‹®é‡Šæ”‘Öó@环引用的内存å—,å¯ÒŽ­¤åQ?D. Hillis 有一ŒDµé£Ž­‘£è€Œç²¾è¾Ÿçš„è®ø™¿°åQ?

一天,一个学生走åˆ?Moon é¢å‰è¯ß_¼š“我知é“如何设计一个更好的垃圾攉™›†å™¨äº†ã€‚我们必™å»è®°å½•æŒ‡å‘æ¯ä¸ªç»“点的指针数目ã€?#8221; Moon è€å¿ƒåœ°ç»™˜q™ä½å­¦ç”Ÿè®²äº†ä¸‹é¢˜q™ä¸ªæ•…事åQ?#8220;一天,一个学生走åˆ?Moon é¢å‰è¯ß_¼š‘我知é“如何设计一个更好的垃圾攉™›†å™¨äº†……’”

D. Hillis 的故事和我们ž®æ—¶å€™å¸¸è¯´çš„“ä»Žå‰æœ‰åñ”山,å±×ƒ¸Šæœ‰ä¸ªåº™ï¼Œåº™é‡Œæœ‰ä¸ªè€å’Œž®?#8221;的故事有异曲åŒå·¥ä¹‹å¦™ã€‚这说明åQŒå•是ä‹É用引用计数算法还ä¸èƒö以解军_žƒåœ¾æ”¶é›†ä¸­çš„æ‰€æœ? é—®é¢˜ã€‚æ­£å› äØ“å¦‚æ­¤åQŒå¼•用计数算法也常常被研½I¶è€…们排除在狭义的垃圾攉™›†½Ž—法之外。当ç„Óž¼Œä½œäؓ一¿U最½Ž€å•ã€æœ€ç›´è§‚的解å†Ïx–¹æ¡ˆï¼Œå¼•用计数½Ž—法本èínå…ähœ‰å…¶ä¸å¯æ›¿ 代的优越性ã€?1980 òq´ä»£å‰åŽåQ?D. P. Friedman åQ?D. S. Wise åQ?H. G. Baker ½{‰äh对引用计数算法进行了数次改进åQŒè¿™äº›æ”¹˜q›ä‹É得引用计数算法åŠå…¶å˜¿U(如åšg˜qŸè®¡æ•°ç®—法等åQ‰åœ¨½Ž€å•的环境下,或是在一些综åˆäº†å¤šç§½Ž—法的现代垃圾收集系¾l? 中ä»ç„¶å¯ä»¥ä¸€å±•èín手ã€?

标记åQ清除( Mark-Sweep åQ‰ç®—æ³?/h3>

½W¬ä¸€¿U实用和完善的垃圾收集算法是 J. McCarthy ½{‰ähåœ?1960 òq´æå‡ºåƈæˆåŠŸåœ°åº”ç”¨äºŽ Lisp 语言的标讎ͼ清除½Ž—法。ä»ä»¥é¤å·„¡º¸ä¸ÞZ¾‹åQŒæ ‡è®ŽÍ¼æ¸…除½Ž—法的执行过½E‹æ˜¯˜q™æ ·çš„:

åˆé¤˜q‡ç¨‹ä¸­ï¼Œ˜¡åŽ…é‡Œçš„æ‰€æœ‰äh都根æ®è‡ªå·Þqš„需è¦å–用é¤å·„¡º¸ã€‚当垃圾攉™›†æœºå™¨äººæƒ³æ”‰™›†åºŸæ—§˜¡å·¾¾U¸çš„æ—¶å€™ï¼Œå®ƒä¼šè®©æ‰€æœ‰ç”¨˜¡çš„人先åœä¸‹æ¥ï¼Œç„¶åŽåQŒä¾‹Æ¡è¯¢é—®é¤ 厅里的æ¯ä¸€ä¸ªähåQ?#8220;你正在用˜¡å·¾¾U¸å—åQŸä½ ç”¨çš„æ˜¯å“ªä¸€å¼ é¤å·„¡º¸åQ?#8221;æœºå™¨äººæ ¹æ®æ¯ä¸ªäh的回½{”å°†äºÞZ»¬æ­£åœ¨ä½¿ç”¨çš„é¤å·„¡º¸ç”ÖM¸Šè®°å·ã€‚询问过½E‹ç»“æŸåŽåQŒæœºå™¨äh在é¤åŽ…é‡Œ å¯ÀL‰¾æ‰€æœ‰æ•£è½åœ¨˜¡æ¡Œä¸Šä¸”没有记å·çš„é¤å·„¡º¸åQˆè¿™äº›æ˜¾ç„‰™ƒ½æ˜¯ç”¨˜q‡çš„废旧˜¡å·¾¾U¸ï¼‰åQŒæŠŠå®ƒä»¬¾lŸç»Ÿæ‰”到垃圾½Ž±é‡Œã€?

正如其å¿U°æ‰€æš—ç¤ºçš„é‚£æ øP¼Œæ ‡è®°åQ清除算法的执行˜q‡ç¨‹åˆ†äØ““标记”å’?#8220;清除”两大阶段。这¿U分步执行的æ€èµ\å¥ å®šäº†çŽ°ä»£åžƒåœ¾æ”¶é›†ç®—æ³•çš„æ€æƒ³åŸºç¡€ã€‚与引用 计数½Ž—法ä¸åŒçš„æ˜¯åQŒæ ‡è®ŽÍ¼æ¸…除½Ž—法ä¸éœ€è¦è¿è¡ŒçŽ¯å¢ƒç›‘‹¹‹æ¯ä¸€‹Æ¡å†…存分é…和指针æ“作åQŒè€Œåªè¦åœ¨“标记”阶段中跟ítªæ¯ä¸€ä¸ªæŒ‡é’ˆå˜é‡çš„æŒ‡å‘——用¾cÖM¼¼æ€èµ\实现的垃 圾收集器也常被åŽäººç»Ÿ¿UîCؓ跟踪攉™›†å™¨ï¼ˆ Tracing Collector åQ?

ä¼´éšç€ Lisp 语言的æˆåŠŸï¼Œæ ‡è®°åQ清除算法也在大多数早期çš?Lisp ˜q行环境中大攑ּ‚彩。尽½Ž¡æœ€åˆç‰ˆæœ¬çš„æ ‡è®°åQ清除算法在今天看楘q˜å­˜åœ¨æ•ˆçއä¸é«˜ï¼ˆæ ‡è®°å’Œæ¸…除是两个相当耗时的过½E‹ï¼‰½{‰è¯¸å¤šç¼ºé™øP¼Œä½†åœ¨åŽé¢çš„讨è®ÞZ¸­åQŒæˆ‘们å¯ä»? 看到åQŒå‡ ä¹Žæ‰€æœ‰çŽ°ä»£åžƒåœ¾æ”¶é›†ç®—æ³•éƒ½æ˜¯æ ‡è®ŽÍ¼æ¸…é™¤æ€æƒ³çš„åšg¾l­ï¼Œä»…此一点, J. McCarthy ½{‰äh在垃圾收集技术方é¢çš„贡献ž®×ƒ¸æ¯«ä¸äºšäºŽä»–们åœ? Lisp 语言上的æˆå°±äº†ã€?

å¤åˆ¶åQ?Copying åQ‰ç®—æ³?/h3>

ä¸ÞZº†è§£å†³æ ‡è®°åQ清除算法在垃圾攉™›†æ•ˆçŽ‡æ–šw¢çš„ç¼ºé™øP¼Œ M. L. Minsky äº?1963 òq´å‘表了著å的论æ–?#8220;一¿Uä‹É用åŒå­˜å‚¨åŒºçš„ Lisp 语言垃圾攉™›†å™¨ï¼ˆ A LISP Garbage Collector Algorithm Using Serial Secondary Storage åQ?#8221;ã€?M. L. Minsky 在该论文中æ˜q°çš„½Ž—法被äh们称为å¤åˆ¶ç®—法,它也è¢?M. L. Minsky 本ähæˆåŠŸåœ°å¼•å…¥åˆ°äº? Lisp 语言的一个实现版本中ã€?

å¤åˆ¶½Ž—法别出心è£åœ°å°†å †ç©ºé—´ä¸€åˆ†äؓ二,òq¶ä‹É用简å•çš„å¤åˆ¶æ“作æ¥å®Œæˆåžƒåœ¾æ”¶é›†å·¥ä½œï¼Œ˜q™ä¸ªæ€èµ\相当有趣。借用˜¡å·¾¾U¸çš„æ¯”å–»åQŒæˆ‘们å¯ä»¥è¿™æ ïL†è§?M. L. Minsky çš„å¤åˆ¶ç®—法:

˜¡åŽ…è¢«åžƒåœ¾æ”¶é›†æœºå™¨äh分æˆå—区和北åŒÞZ¸¤ä¸ªå¤§ž®å®Œå…¨ç›¸åŒçš„部分。刘¡æ—¶åQŒæ‰€æœ‰äh都先在å—区用˜¡ï¼ˆå› äØ“½Iºé—´æœ‰é™åQŒç”¨˜¡äh数自然也ž®†å‡ž®‘一åŠï¼‰åQŒç”¨˜¡æ—¶å? ä»¥éšæ„ä‹É用é¤å·„¡º¸ã€‚当垃圾攉™›†æœºå™¨äºø™®¤ä¸ºæœ‰å¿…è¦å›žæ”¶åºŸæ—§˜¡å·¾¾U¸æ—¶åQŒå®ƒä¼šè¦æ±‚所有用˜¡è€…以最快的速度从å—åŒø™{¿UÕdˆ°åŒ—区åQŒåŒæ—‰™šíw«æºå¸¦è‡ªå·±æ­£åœ¨ä‹É用的˜¡å·¾¾U¸ã€? ½{‰æ‰€æœ‰äh都è{¿UÕdˆ°åŒ—区之åŽåQŒåžƒåœ¾æ”¶é›†æœºå™¨ähåªè¦½Ž€å•地把å—åŒÞZ¸­æ‰€æœ‰æ•£è½çš„˜¡å·¾¾U¸æ‰”˜q›åžƒåœ„¡®±ž®Þq®—完æˆä»ÕdŠ¡äº†ã€‚ä¸‹ä¸€‹Æ¡åžƒåœ¾æ”¶é›†çš„工作˜q‡ç¨‹ä¹Ÿå¤§è‡´ç±»ä¼û|¼ŒæƒŸä¸€çš„ä¸ åŒåªæ˜¯äh们的转移方å‘å˜æˆäº†ä»ŽåŒ—区到å—区。如此åó@环往å¤ï¼Œæ¯æ¬¡åžƒåœ¾æ”‰™›†éƒ½åªéœ€½Ž€å•地转移åQˆä¹Ÿž®±æ˜¯å¤åˆ¶åQ‰ä¸€‹Æ¡ï¼Œåžƒåœ¾æ”‰™›†é€Ÿåº¦æ— ä¸Žä¼¦æ¯”——当ç„Óž¼Œå¯¹äºŽç”¨é¤è€…å¾€ ˜q”奔波于å—北两区之间的辛劻I¼Œåžƒåœ¾æ”‰™›†æœºå™¨äººæ˜¯å†³ä¸ä¼šæµéœ²å‡ºä¸æ¯«æ€œæ‚¯çš„ã€?

M. L. Minsky çš„å‘æ˜Žç»å¯¹ç®—得上一¿U奇æ€å¦™æƒŸë€‚分区ã€å¤åˆ¶çš„æ€èµ\ä¸ä»…大幅æé«˜äº†åžƒåœ¾æ”¶é›†çš„æ•ˆçއåQŒè€Œä¸”也将原本¾Jçº·å¤æ‚的内存分é…算法å˜å¾—剿‰€æœªæœ‰åœ°ç®€æ˜Žå’Œæ‰ÆD¦åQˆæ—¢ç„¶æ¯‹Æ? 内存回收都是å¯ÒŽ•´ä¸ªåŠåŒºçš„回收åQŒå†…å­˜åˆ†é…æ—¶ä¹Ÿå°±ä¸ç”¨è€ƒè™‘内存¼„Žç‰‡½{‰å¤æ‚情况,åªè¦¿UÕdŠ¨å †é¡¶æŒ‡é’ˆåQŒæŒ‰™åºåºåˆ†é…内存ž®±å¯ä»¥äº†åQ‰ï¼Œ˜q™ç®€ç›´æ˜¯ä¸ªå¥‡˜q¹ï¼ä¸è¿‡åQŒä“Q何奇 ˜q¹çš„出现都有一定的代ä­håQŒåœ¨åžƒåœ¾æ”‰™›†æŠ€æœ¯ä¸­åQŒå¤åˆ¶ç®—法æé«˜æ•ˆçŽ‡çš„ä»£ä­h是äh为地ž®†å¯ç”¨å†…存羃ž®äº†ä¸€åŠã€‚实è¯å®žè¯ß_¼Œ˜q™ä¸ªä»£ä­h未å…也太高了一些ã€?

无论优缺点如何,å¤åˆ¶½Ž—法在实践中都获得了å¯ä»¥ä¸Žæ ‡è®ŽÍ¼æ¸…除½Ž—法相比拟的æˆåŠŸã€‚é™¤äº?M. L. Minsky 本ähåœ?Lisp 语言中的工作以外åQŒä»Ž 1960 òq´ä»£æœ«åˆ° 1970 òq´ä»£åˆï¼Œ R. R. Fenichel å’?J. C. Yochelson ½{‰äh也相¾l§åœ¨ Lisp 语言的ä¸åŒå®žçŽîC¸­å¯¹å¤åˆ¶ç®—法进行了改进åQ?S. Arnborg 更是æˆåŠŸåœ°å°†å¤åˆ¶½Ž—法应用åˆîCº† Simula 语言中ã€?

è‡Ïx­¤åQŒåžƒåœ¾æ”¶é›†æŠ€æœ¯çš„三大传统½Ž—æ³•â€”â€”å¼•ç”¨è®¡æ•°ç®—æ³•ã€æ ‡è®ŽÍ¼æ¸…除½Ž—法和å¤åˆ¶ç®—法——都已在 1960 òq´å‰åŽç›¸¾l§é—®ä¸–ï¼Œä¸‰ç§½Ž—æ³•å„æœ‰æ‰€é•¿ï¼Œä¹Ÿéƒ½å­˜åœ¨è‡´å‘½çš„缺陗÷€‚从 1960 òq´ä»£åŽæœŸå¼€å§‹ï¼Œç ”究者的主覾_‘ÖŠ›é€æ¸è½¬å‘对这三ç§ä¼ ç»Ÿ½Ž—法˜q›è¡Œæ”¹è¿›æˆ–æ•´åˆï¼Œä»¥æ‰¬é•‰K¿çŸ­ï¼Œé€‚应½E‹åºè®¾è®¡è¯­è¨€å’Œè¿è¡ŒçŽ¯å¢ƒå¯¹åžƒåœ¾æ”‰™›†çš„æ•ˆçŽ‡å’Œå®žæ—¶æ€§æ‰€æå‡ºçš„æ›´é«? è¦æ±‚ã€?

èµ°å‘æˆç†Ÿ

ä»?1970 òq´ä»£å¼€å§‹ï¼Œéšç€¿U‘学研究和应用实è·ëŠš„䏿–­æ·±å…¥åQŒäh们逿¸æ„识刎ͼŒä¸€ä¸ªç†æƒ³çš„垃圾攉™›†å™¨ä¸åº”在˜q行时导致应用程åºçš„æš‚åœåQŒä¸åº”é¢å¤–å ç”¨å¤§é‡çš„内存½Iºé—´å’? CPU 资æºåQŒè€Œä¸‰¿Uä¼ ¾lŸçš„垃圾攉™›†½Ž—法都无法满­‘Œ™¿™äº›è¦æ±‚。äh们必™åÀL出更新的½Ž—法或æ€èµ\åQŒä»¥è§£å†³å®žè·µä¸­ç¢°åˆ°çš„诸多éšùN¢˜ã€‚当æ—Óž¼Œç ”究者的努力目标包括åQ?

½W¬ä¸€åQŒæé«˜åžƒåœ¾æ”¶é›†çš„æ•ˆçŽ‡ã€‚ä‹É用标讎ͼ清除½Ž—æ³•çš„åžƒåœ¾æ”¶é›†å™¨åœ¨å·¥ä½œæ—¶è¦æ¶ˆè€—相当多çš?CPU 资æºã€‚早期的 Lisp ˜q行环境攉™›†å†…存垃圾的时间竟å åˆ°äº†ç³»¾lŸæ€»è¿è¡Œæ—¶é—´çš„ 40% åQ——垃圾收集效率的低下直接造就äº?Lisp 语言在执行速度斚w¢çš„åå声åQ›ç›´åˆîC»Šå¤©ï¼Œè®¸å¤šäºø™¿˜æ¡äšgå射似地误以为所æœ?Lisp ½E‹åºéƒ½å¥‡æ…¢æ— æ¯”ã€?

½W¬äºŒåQŒå‡ž®‘垃圾收集时的内存å ç”¨ã€‚这一问题主è¦å‡ºçŽ°åœ¨å¤åˆ¶ç®—法中。尽½Ž¡å¤åˆ¶ç®—法在效率上获得了质的½Hç ´åQŒä½†ç‰ºç‰²ä¸€åŠå†…存空间的代ä­hä»ç„¶æ˜¯å·¨å¤§çš„。在计算机å‘展的早期åQŒåœ¨å†…å­˜ä»äh ¼ä»?KB 计算的日å­é‡ŒåQŒæµªè´¹å®¢æˆïLš„一åŠå†…存空间简直就是在å˜ç›¸æ•²è¯ˆæˆ–拦路打劫ã€?

½W¬ä¸‰åQŒå¯»æ‰‘Ö®žæ—¶çš„垃圾攉™›†½Ž—法。无论执行效率如何,三ç§ä¼ ç»Ÿçš„垃圾收集算法在执行垃圾攉™›†ä»ÕdŠ¡æ—‰™ƒ½å¿…须打断½E‹åºçš„当å‰å·¥ä½œã€‚è¿™¿U因垃圾攉™›†è€Œé€ æˆçš? 延时是许多程åºï¼Œç‰¹åˆ«æ˜¯æ‰§è¡Œå…³é”®ä“Q务的½E‹åºæ²¡æœ‰åŠžæ³•å®¹å¿çš„。如何对传统½Ž—法˜q›è¡Œæ”¹è¿›åQŒä»¥ä¾¿å®žçŽîC¸€¿U在åŽå°æ‚„悄执行åQŒä¸å½±å“——或臛_°‘看上åŽÖM¸å½±å“——当å‰? ˜q›ç¨‹çš„实时垃圾收集器åQŒè¿™æ˜„¡„¶æ˜¯ä¸€ä»¶æ›´å…ähŒ‘战性的工作ã€?

ç ”ç©¶è€…ä»¬æŽ¢å¯»æœªçŸ¥é¢†åŸŸçš„å†³å¿ƒå’Œç ”ç©¶å·¥ä½œçš„è¿›å±•é€Ÿåº¦åŒæ ·ä»¤äh惊奇åQšåœ¨ 1970 òq´ä»£åˆ?1980 òq´ä»£çš„短短å几年中,一大批在实用系¾lŸä¸­è¡¨çŽ°ä¼˜å¼‚çš„æ–°½Ž—法和新æ€èµ\脱颖而出。正是因为有了这些日­‘‹æˆç†Ÿçš„垃圾攉™›†½Ž—法åQŒä»Šå¤©çš„æˆ‘们æ‰èƒ½åœ?Java æˆ? .NET æä¾›çš„è¿è¡ŒçŽ¯å¢ƒä¸­éšå¿ƒæ‰€‹Æ²åœ°åˆ†é…内存å—,而ä¸å¿…担心空间释放时的风险ã€?

标记åQæ•´ç†ï¼ˆ Mark-Compact åQ‰ç®—æ³?/h3>

标记åQæ•´ç†ç®—法是标记åQ清除算法和å¤åˆ¶½Ž—法的有机结åˆã€‚把标记åQ清除算法在内存å ç”¨ä¸Šçš„优点和å¤åˆ¶ç®—法在执行效率上的牚w•¿¾l¼åˆèµäh¥åQŒè¿™æ˜¯æ‰€æœ‰äh都希 望看到的¾l“果。丘q‡ï¼Œä¸¤ç§åžƒåœ¾æ”‰™›†½Ž—法的整åˆåƈä¸åƒ 1 åŠ?1 ½{‰äºŽ 2 那样½Ž€å•,我们必须引入一些全新的æ€èµ\ã€?1970 òq´å‰åŽï¼Œ G. L. Steele åQ?C. J. Cheney å’?D. S. Wise ½{‰ç ”½I¶è€…陆¾l­æ‰¾åˆîCº†æ­£ç¡®çš„æ–¹å‘,标记åQæ•´ç†ç®—æ³•çš„è½®å»“ä¹Ÿé€æ¸æ¸…晰了è“væ¥ï¼š

在我们熟悉的˜¡åŽ…é‡Œï¼Œ˜q™ä¸€‹Æ¡ï¼Œåžƒåœ¾æ”‰™›†æœºå™¨äºÞZ¸å†æŠŠ˜¡åŽ…åˆ†æˆä¸¤ä¸ªå—åŒ—åŒºåŸŸäº†ã€‚éœ€è¦æ‰§è¡Œåžƒåœ¾æ”¶é›†ä“Q务时åQŒæœºå™¨äh先执行标讎ͼ清除½Ž—法的第一个步骤,ä¸? 所有ä‹É用中的é¤å·„¡º¸ç”Õd¥½æ ‡è®°åQŒç„¶åŽï¼Œæœºå™¨äººå‘½ä»¤æ‰€æœ‰å°±˜¡è€…带上有标记的é¤å·„¡º¸å‘é¤åŽ…çš„å—é¢é›†ä¸­åQŒåŒæ—¶æŠŠæ²¡æœ‰æ ‡è®°çš„废旧é¤å·„¡º¸æ‰”员¡åŽ…åŒ—é¢ã€‚这样一æ¥ï¼Œæœºå™¨ äººåªæ¶ˆç«™åœ¨é¤åŽ…åŒ—é¢ï¼Œæ€€æŠ±åžƒåœ„¡®±åQŒè¿ŽæŽ¥æ‰‘é¢è€Œæ¥çš„废旧é¤å·„¡º¸ž®Þp¡Œäº†ã€?

实验表明åQŒæ ‡è®ŽÍ¼æ•´ç†½Ž—法的æ€ÖM½“执行效率高于标记åQ清除算法,åˆä¸åƒå¤åˆ¶ç®—法那样需è¦ç‰ºç‰²ä¸€åŠçš„存储½Iºé—´åQŒè¿™æ˜„¡„¶æ˜¯ä¸€¿Uéžå¸¸ç†æƒ³çš„¾l“果。在许多çŽîC»£çš„垃圾收集器中,äºÞZ»¬éƒ½ä‹É用了标记åQæ•´ç†ç®—法或其改˜q›ç‰ˆæœ¬ã€?

å¢žé‡æ”‰™›†åQ?Incremental Collecting åQ‰ç®—æ³?/h3>

å¯¹å®žæ—¶åžƒåœ¾æ”¶é›†ç®—æ³•çš„ç ”ç©¶ç›´æŽ¥å¯ÆD‡´äº†å¢žé‡æ”¶é›†ç®—法的诞生ã€?

最åˆï¼ŒäºÞZ»¬å…³äºŽå®žæ—¶åžƒåœ¾æ”‰™›†çš„æƒ³æ³•是˜q™æ ·çš„:ä¸ÞZº†˜q›è¡Œå®žæ—¶çš„垃圾收集,å¯ä»¥è®¾è®¡ä¸€ä¸ªå¤š˜q›ç¨‹çš„è¿è¡ŒçŽ¯å¢ƒï¼Œæ¯”å¦‚ç”¨ä¸€ä¸ªè¿›½E‹æ‰§è¡Œåžƒåœ¾æ”¶é›†å·¥ä½œï¼Œå¦ä¸€ä¸ªè¿›½E‹æ‰§è¡Œç¨‹åºä»£ç ã€‚这样一æ¥ï¼Œåžƒåœ¾æ”‰™›†å·¥ä½œçœ‹ä¸ŠåŽÕd°±ä»¿ä½›æ˜¯åœ¨åŽå°æ‚„悄完æˆçš„,ä¸ä¼šæ‰“æ–­½E‹åºä»£ç çš„è¿è¡Œã€?

在收集é¤å·„¡º¸çš„例å­ä¸­åQŒè¿™ä¸€æ€èµ\å¯ä»¥è¢«ç†è§£äØ“åQšåžƒåœ¾æ”¶é›†æœºå™¨äh在äh们用˜¡çš„åŒæ—¶å¯ÀL‰¾åºŸå¼ƒçš„é¤å·„¡º¸òq¶å°†å®ƒä»¬æ‰”到垃圾½Ž±é‡Œã€‚这个看似简å•çš„æ€èµ\会在设计 和实现时¼„îC¸Š˜q›ç¨‹é—´å†²½Hçš„éšùN¢˜ã€‚比如说åQŒå¦‚果垃圾收集进½E‹åŒ…括标记和清除两个工作阶段åQŒé‚£ä¹ˆï¼Œåžƒåœ¾æ”‰™›†å™¨åœ¨½W¬ä¸€é˜¶æ®µä¸­è¾›è¾›è‹¦è‹¦æ ‡è®°å‡ºçš„结果很å¯èƒ½è¢«å¦ä¸€ä¸? ˜q›ç¨‹ä¸­çš„内存æ“作代ç ä¿®æ”¹å¾—é¢ç›®å…¨éžï¼Œä»¥è‡³äºŽç¬¬äºŒé˜¶ŒD늚„工作没有办法开展ã€?

M. L. Minsky å’?D. E. Knuth 对实时垃圾收集过½E‹ä¸­çš„æŠ€æœ¯éš¾ç‚¹è¿›è¡Œäº†æ—©æœŸçš„ç ”½IÓž¼Œ G. L. Steele äº? 1975 òq´å‘è¡¨äº†é¢˜äØ““多进½E‹æ•´ç†çš„垃圾攉™›†åQ?Multiprocessing compactifying garbage collection åQ?#8221;的论文,æè¿°äº†ä¸€¿U被åŽäh¿UîCØ““ Minsky-Knuth-Steele ½Ž—法”的实时垃圾收集算法ã€?E. W. Dijkstra åQ?L. Lamport åQ?R. R. Fenichel å’?J. C. Yochelson ½{‰äh也相¾l§åœ¨æ­¤é¢†åŸŸåšå‡ÞZº†å„自的èµA献ã€?1978 òqß_¼Œ H. G. Baker å‘表äº?#8220;串行计算æœÞZ¸Šçš„å®žæ—¶è¡¨å¤„ç†æŠ€æœ¯ï¼ˆ List Processing in Real Time on a Serial Computer åQ?#8221;一文,¾pÈ»Ÿé˜è¿°äº†å¤š˜q›ç¨‹çŽ¯å¢ƒä¸‹ç”¨äºŽåžƒåœ¾æ”¶é›†çš„å¢žé‡æ”‰™›†½Ž—法ã€?

å¢žé‡æ”‰™›†½Ž—法的基¼‹€ä»æ˜¯ä¼ ç»Ÿçš„æ ‡è®ŽÍ¼æ¸…除和å¤åˆ¶ç®—æ³•ã€‚å¢žé‡æ”¶é›†ç®—法通过对进½E‹é—´å†²çªçš„妥善处ç†ï¼Œå…许垃圾攉™›†˜q›ç¨‹ä»¥åˆ†é˜¶æ®µçš„æ–¹å¼å®Œæˆæ ‡è®°ã€æ¸…ç†æˆ–å¤? 制工作。详¾l†åˆ†æžå„¿Uå¢žé‡æ”¶é›†ç®—æ³•çš„å†…éƒ¨æœºç†æ˜¯ä¸€ä»¶ç›¸å½“ç¹ç的事情åQŒåœ¨˜q™é‡ŒåQŒè¯»è€…们需è¦äº†è§£çš„仅仅是: H. G. Baker ½{‰äh的努力已¾l将实时垃圾攉™›†çš„æ¢¦æƒ›_˜æˆäº†çŽ°å®žåQŒæˆ‘们å†ä¹Ÿä¸ç”¨äؓ垃圾攉™›†æ‰“æ–­½E‹åºçš„è¿è¡Œè€Œçƒ¦æégº†ã€?

分代攉™›†åQ?Generational Collecting åQ‰ç®—æ³?/h3>

和大多数软äšgå¼€å‘æŠ€æœ¯ä¸€æ øP¼Œ¾lŸè®¡å­¦åŽŸç†æ€»èƒ½åœ¨æŠ€æœ¯å‘展的˜q‡ç¨‹ä¸­è“v到强力催化剂的作用ã€?1980 òq´å‰åŽï¼Œå–„于在研½I¶ä¸­ä½¿ç”¨¾lŸè®¡åˆ†æžçŸ¥è¯†çš„æŠ€æœ¯äh员å‘玎ͼŒå¤§å¤šæ•°å†…å­˜å—的生存周期都比较短,垃圾攉™›†å™¨åº”å½“æŠŠæ›´å¤šçš„ç²¾åŠ›æ”¾åœ¨æ£€æŸ¥å’Œæ¸…ç†æ–°åˆ†é…的内存å—上。这 个å‘现对于垃圾收集技术的价值å¯ä»¥ç”¨˜¡å·¾¾U¸çš„例孿¦‚括如下åQ?

如果垃圾攉™›†æœºå™¨äºø™ƒöå¤Ÿèªæ˜Žï¼Œäº‹å…ˆæ‘¸æ¸…了é¤åŽ…é‡Œæ¯ä¸ªäººåœ¨ç”¨é¤æ—¶ä‹É用é¤å·„¡º¸çš„习惯——比如有些äh喜欢在用˜¡å‰åŽå„用掉一张é¤å·„¡º¸åQŒæœ‰çš„äh喜欢自始至终 攥ç€ä¸€å¼ é¤å·„¡º¸ä¸æ”¾åQŒæœ‰çš„ähåˆ™æ¯æ‰“一个喷åšå°±ç”¨å޻䏀张é¤å·„¡º¸â€”—机器ähž®±å¯ä»¥åˆ¶å®šå‡ºæ›´å®Œå–„çš„˜¡å·¾¾U¸å›žæ”¶è®¡åˆ’,òq¶æ€ÀL˜¯åœ¨äh们刚扔掉˜¡å·¾¾U¸æ²¡å¤šä¹…ž®±æŠŠåžƒåœ¾æ? 走。这¿U基于统计学原ç†çš„åšæ³•当然å¯ä»¥è®©˜¡åŽ…çš„æ•´‹z度æˆå€æé«˜ã€?

D. E. Knuth åQ?T. Knight åQ?G. Sussman å’?R. Stallman ½{‰äh对内存垃圄¡š„分类处ç†åšäº†æœ€æ—©çš„研究ã€?1983 òqß_¼Œ H. Lieberman å’?C. Hewitt å‘表了题ä¸?#8220;åŸÞZºŽå¯¹è±¡å¯¿å‘½çš„一¿U实时垃圾收集器åQ?A real-time garbage collector based on the lifetimes of objects åQ?#8221;的论文。这½‹‡è‘—å的论文标志ç€åˆ†ä»£æ”‰™›†½Ž—法的正å¼è¯žç”Ÿã€‚æ­¤åŽï¼Œåœ?H. G. Baker åQ?R. L. Hudson åQ?J. E. B. Moss ½{‰äh的共åŒåŠªåŠ›ä¸‹åQŒåˆ†ä»£æ”¶é›†ç®—æ³•é€æ¸æˆäؓ了垃圾收集领域里的主‹¹æŠ€æœ¯ã€?

分代攉™›†½Ž—法通常ž®†å †ä¸­çš„å†…å­˜å—æŒ‰å¯¿å‘½åˆ†äؓ两类åQŒå¹´è€çš„和年è½Èš„。垃圾收集器使用ä¸åŒçš„æ”¶é›†ç®—法或攉™›†½{–ç•¥åQŒåˆ†åˆ«å¤„ç†è¿™ä¸¤ç±»å†…å­˜å—,òq¶ç‰¹åˆ«åœ°æŠŠä¸»è¦? 工作旉™—´èŠ±åœ¨å¤„ç†òq´è½»çš„内存å—上。分代收集算法ä‹É垃圾攉™›†å™¨åœ¨æœ‰é™çš„èµ„æºæ¡ä»¶ä¸‹åQŒå¯ä»¥æ›´ä¸ºæœ‰æ•ˆåœ°å·¥ä½œâ€”—这¿U效率上的æé«˜åœ¨ä»Šå¤©çš?Java 虚拟æœÞZ¸­å¾—åˆ°äº†æœ€å¥½çš„è¯æ˜Žã€?

应用‹¹ªæ½®

Lisp 是垃圾收集技术的½W¬ä¸€ä¸ªå—ç›Šè€…ï¼Œä½†æ˜¾ç„¶ä¸æ˜¯æœ€åŽä¸€ä¸ªã€‚在 Lisp 语言之åŽåQŒè®¸è®¸å¤šå¤šä¼ ¾lŸçš„ã€çŽ°ä»£çš„ã€åŽçŽîC»£çš„语­a€å·²ç»æŠŠåžƒåœ¾æ”¶é›†æŠ€æœ¯æ‹‰å…¥äº†è‡ªå·±çš„æ€€æŠ±ã€‚éšä¾¿ä‹D几个例å­å§ï¼šè¯žç”Ÿäº?1964 òq´çš„ Simula 语言åQ?1969 òq´çš„ Smalltalk 语言åQ?1970 òq´çš„ Prolog 语言åQ?1973 òq´çš„ ML 语言åQ?1975 òq´çš„ Scheme 语言åQ?1983 òq´çš„ Modula-3 语言åQ?1986 òq´çš„ Eiffel 语言åQ?1987 òq´çš„ Haskell 语言……它们都先åŽä‹É用了自动垃圾攉™›†æŠ€æœ¯ã€‚当ç„Óž¼Œæ¯ä¸€¿U语­a€ä½¿ç”¨çš„垃圾收集算法å¯èƒ½ä¸ž®½ç›¸åŒï¼Œå¤§å¤šæ•°è¯­­a€å’Œè¿è¡ŒçŽ¯å¢ƒç”šè‡›_Œæ—¶ä‹É用了多ç§åžƒåœ¾æ”‰™›†½Ž—法。但 无论怎样åQŒè¿™äº›å®žä¾‹éƒ½è¯´æ˜ŽåQŒåžƒåœ¾æ”¶é›†æŠ€æœ¯ä»Žè¯žç”Ÿçš„那一天è“vž®×ƒ¸æ˜¯ä¸€¿U曲高和寡的“学院‹z?#8221;技术ã€?

对于我们熟悉çš?C å’?C++ 语言åQŒåžƒåœ¾æ”¶é›†æŠ€æœ¯ä¸€æ ·å¯ä»¥å‘挥巨大的功效。正如我们在学校中就已ç»çŸ¥é“çš„é‚£æ øP¼Œ C å’?C++ 语言本èínòq¶æ²¡æœ‰æä¾›åžƒåœ¾æ”¶é›†æœºåˆÓž¼Œä½†è¿™òq¶ä¸å¦¨ç¢æˆ‘们在程åºä¸­ä½¿ç”¨å…ähœ‰åžƒåœ¾æ”‰™›†åŠŸèƒ½çš„å‡½æ•°åº“æˆ–ç±»åº“ã€‚ä¾‹å¦‚ï¼Œæ—©åœ¨ 1988 òqß_¼Œ H. J. Boehm å’?A. J. Demers ž®±æˆåŠŸåœ°å®žçŽ°äº†ä¸€¿Uä‹É用ä¿å®ˆåžƒåœ¾æ”¶é›†ç®—法( Conservative GC Algorithmic åQ‰çš„函数库(å‚è§ http://www.hpl.hp.com/personal/Hans_Boehm/gc åQ‰ã€‚我们å¯ä»¥åœ¨ C 语言æˆ?C++ 语言中ä‹É用该函数库完æˆè‡ªåŠ¨åžƒåœ¾æ”¶é›†åŠŸèƒ½ï¼Œå¿…è¦æ—Óž¼Œç”šè‡³˜q˜å¯ä»¥è®©ä¼ ç»Ÿçš?C/C++ 代ç ä¸Žä‹É用自动垃圾收集功能的 C/C++ 代ç åœ¨ä¸€ä¸ªç¨‹åºé‡ŒååŒå·¥ä½œã€?

1995 òq´è¯žç”Ÿçš„ Java 语言在一夜之间将垃圾攉™›†æŠ€æœ¯å˜æˆäº†è½¯äšgå¼€å‘领域里最为æµè¡Œçš„æŠ€æœ¯ä¹‹ä¸€ã€‚从æŸç§è§’度è¯ß_¼Œæˆ‘们很难分清½I¶ç«Ÿæ˜? Java 从垃圾收集中å—益åQŒè¿˜æ˜¯åžƒåœ¾æ”¶é›†æŠ€æœ¯æœ¬íw«å€?Java 的普åŠè€Œæ‰¬å。值得注æ„的是åQŒä¸åŒç‰ˆæœ¬çš„ Java 虚拟æœÞZ‹É用的垃圾攉™›†æœºåˆ¶òq¶ä¸å®Œå…¨ç›¸åŒåQ?Java 虚拟机其实也¾l过了一个从½Ž€å•åˆ°å¤æ‚çš„å‘展过½E‹ã€‚在 Java 虚拟机的 1.4.1 版中åQŒäh们å¯ä»¥ä½“验到的垃圾收集算法就包括分代攉™›†ã€å¤åˆ¶æ”¶é›†ã€å¢žé‡æ”¶é›†ã€æ ‡è®ŽÍ¼æ•´ç†ã€åƈ行å¤åˆÓž¼ˆ Parallel Copying åQ‰ã€åƈ行清除( Parallel Scavenging åQ‰ã€åƈå‘( Concurrent åQ‰æ”¶é›†ç­‰è®¸å¤š¿U, Java ½E‹åº˜qè¡Œé€Ÿåº¦çš„ä¸æ–­æå‡åœ¨å¾ˆå¤§½E‹åº¦ä¸Šåº”该归功于垃圾攉™›†æŠ€æœ¯çš„å‘展与完善ã€?

ž®½ç®¡åކå²ä¸Šå·²¾l有许多包å«åžƒåœ¾æ”‰™›†æŠ€æœ¯çš„应用òq›_°å’Œæ“作系¾lŸå‡ºçŽŽÍ¼Œä½?Microsoft .NET å´æ˜¯½W¬ä¸€¿U真正实用化的ã€åŒ…å«äº†åžƒåœ¾æ”‰™›†æœºåˆ¶çš„通用语言˜q行环境。事实上åQ?.NET òq›_°ä¸Šçš„æ‰€æœ‰è¯­­a€åQŒåŒ…æ‹?C# ã€?Visual Basic .NET ã€?Visual C++ .NET ã€?J# ½{‰ç­‰åQŒéƒ½å¯ä»¥é€šè¿‡å‡ ä¹Žå®Œå…¨ç›¸åŒçš„æ–¹å¼ä‹Éç”?.NET òq›_°æä¾›çš„垃圾收集机制。我们似乎å¯ä»¥æ–­­a€åQ?.NET 是垃圾收集技术在应用领域里的一‹Æ¡é‡å¤§å˜é©ï¼Œå®ƒä‹É垃圾攉™›†æŠ€æœ¯ä»Žä¸€¿U啾U¯çš„æŠ€æœ¯å˜æˆäº†åº”用环境乃至æ“作¾pÈ»Ÿä¸­çš„一¿U内在文化。这¿Uå˜é©å¯¹æœªæ¥è½¯äšg开呿Ѐæœ? 的媄å“力也许è¦è¿œ˜qœè¶…˜q?.NET òq›_°æœ¬èín的商业ä­h倹{€?

大势所­‘?/h3>

今天åQŒè‡´åŠ›äºŽåžƒåœ¾æ”‰™›†æŠ€æœ¯ç ”½I¶çš„äºÞZ»¬ä»åœ¨ä¸æ‡ˆåŠªåŠ›åQŒä»–们的研究方å‘包括分布å¼ç³»¾lŸçš„垃圾攉™›†ã€å¤æ‚äº‹åŠ¡çŽ¯å¢ƒä¸‹çš„åžƒåœ¾æ”¶é›†ã€æ•°æ®åº“½{‰ç‰¹å®šç³»¾lŸçš„垃圾攉™›†½{‰ç­‰ã€?

但在½E‹åºå‘˜ä¸­é—ß_¼Œä»æœ‰ä¸å°‘人对垃圾攉™›†æŠ€æœ¯ä¸å±‘一™å¾ï¼Œä»–们宿„¿ç›æ€¿¡è‡ªå·±é€è¡Œ¾~–写çš?free æˆ?delete 命ä×oåQŒä¹Ÿä¸æ„¿æŠŠåžƒåœ¾æ”¶é›†çš„é‡ä“Qäº¤ç»™é‚£äº›åœ¨ä»–ä»¬çœ‹æ¥æ—¢è ¢åˆ½W¨çš„垃圾攉™›†å™¨ã€?

æˆ‘ä¸ªäºø™®¤ä¸ºï¼Œåžƒåœ¾æ”‰™›†æŠ€æœ¯çš„æ™®åŠæ˜¯å¤§åŠ¿æ‰€­‘‹ï¼Œ˜q™å°±åƒç”Ÿ‹zÖM¼š­‘Šæ¥­‘Šå¥½ä¸€æ äh¯‹åº¸ç½®ç–‘。今天的½E‹åºå‘˜ä¹Ÿè®æ€¼šå› äؓ垃圾攉™›†å™¨è¦å ç”¨ä¸€å®šçš„ CPU 资æºè€Œå¯¹å…¶æœ›è€Œå´æ­¥ï¼Œä½†äºŒå多òq´å‰çš„程åºå‘˜˜q˜æ›¾å› äؓ高çñ”è¯­è¨€é€Ÿåº¦å¤ªæ…¢è€ŒåšæŒç”¨æœºå™¨è¯­è¨€å†™ç¨‹åºå‘¢åQ在¼‹¬äšg速度日新月异的今天,我们是è¦å惜那一点儿旉™—´æŸè€? 而踟íw‡ä¸å‰ï¼Œ˜q˜æ˜¯è¯¥åšå®šä¸¿UÕdœ°ç«™åœ¨ä»£ç å’Œè¿è¡ŒçŽ¯å¢ƒçš„å‡€åŒ–å‰‚â€”â€”åžƒåœ¾æ”¶é›†çš„ä¸€è¾¹å‘¢åQ?

[王å’刚,2003òq?2月]



]]>
垃圾回收工作机制 学习自《Java½E‹åºå‘? 上ç­é‚£ç‚¹äº‹å„¿ã€?/title><link>http://m.tkk7.com/gen-sky/articles/285795.html</link><dc:creator>星期äº?/dc:creator><author>星期äº?/author><pubDate>Tue, 07 Jul 2009 05:23:00 GMT</pubDate><guid>http://m.tkk7.com/gen-sky/articles/285795.html</guid><wfw:comment>http://m.tkk7.com/gen-sky/comments/285795.html</wfw:comment><comments>http://m.tkk7.com/gen-sky/articles/285795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/gen-sky/comments/commentRss/285795.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/gen-sky/services/trackbacks/285795.html</trackback:ping><description><![CDATA[<p><strong>4.5 å†…存垃圾回收问题</strong></p> <p><strong>那本谭浩å¼ÞZ¸»¾~–çš„Java入门教æè¯ß_¼š</strong></p> <p><font face="楷体_GB2312">……</font></p> <p><font face="楷体_GB2312">1ã€ç®€å•æ€?/font></p> <p><font face="楷体_GB2312">设计Java语言的出å‘点ž®±æ˜¯å®ÒŽ˜“¾~–程åQŒä¸éœ€è¦æ·±å¥¥çš„知识。Java语言的风格å分接˜q‘C++语言åQŒä½†è¦æ¯”C++½Ž€å•得多。Javaèˆå¼ƒäº†ä¸€äº›ä¸å¸¸ç”¨çš„ã€éš¾ä»¥ç†è§£çš„ã€å®¹æ˜“æØœæ·†çš„æˆåˆ†åQŒå¦‚˜qç®—½W¦é‡è½½ã€å¤š¾l§æ‰¿½{‰ã€‚增加了自动垃圾æœé›†åŠŸèƒ½åQŒç”¨äºŽå›žæ”¶ä¸å†ä‹É用的内存区域。这ä¸ä½†ä½¿ç¨‹åºæ˜“于编写,而且大大å‡å°‘了由于内存分é…而引å‘的问题ã€?/font></p> <p><font face="楷体_GB2312">……</font></p> <p>˜q™æ ·¾cÖM¼¼çš„æ˜q°å‡ºçŽ°åœ¨ä¼—å¤šçš„Java入门¾U§æ•™æä¸­åQŒéžå¸¸å®¹æ˜“让äºÞZ»¬å¿½ç•¥äº†å†…存垃圑֛žæ”¶çš„问题åQŒå…¶å®žJava的垃圑֛žæ”‰™—®˜q˜æ˜¯éœ€è¦å…³æ³¨ä¸€ä¸‹çš„。这个问题在招è˜å•ä½çš„笔试题中出现的频率也比较高åQŒæˆ‘们需è¦å¥½å¥½çš„研究一下Java的垃圑֛žæ”¶æœºåˆ¶ã€?/p> <p><strong>4.5.1 ä»€ä¹ˆæ˜¯å†…存垃圾åQŒå“ªäº›å†…存符åˆåžƒåœ„¡š„标准</strong></p> <p>我们在å‰é¢è®²˜q‡äº†åQŒå †æ˜¯ä¸€ä¸?˜q行æ—?æ•°æ®åŒºï¼Œæ˜¯é€šè¿‡"new"½{‰æŒ‡ä»¤å¾ç«‹çš„åQŒJava的堆是由Java的垃圑֛žæ”¶æœºåˆ¶æ¥è´Ÿè´£å¤„ç†çš„,堆是动æ€åˆ†é…内存大ž®ï¼Œåžƒåœ¾æ”‰™›†å™¨å¯ä»¥è‡ªåŠ¨å›žæ”¶ä¸å†ä‹É用的内存½Iºé—´ã€?/p> <p>也就是说åQŒæ‰€è°“çš„"内存垃圾"是指在堆上开辟的内存½Iºé—´åœ¨ä¸ç”¨çš„æ—¶å€™å°±å˜æˆäº?垃圾"ã€?/p> <p>C++或其他程åºè®¾è®¡è¯­­a€ä¸­ï¼Œå¿…é¡»ç”Þq¨‹åºå‘˜è‡ªè¡Œå£°æ˜Žäº§ç”Ÿå’Œå›žæ”Óž¼Œå¦åˆ™å…¶ä¸­çš„资æºå°†æ¶ˆè€—,造æˆèµ„æºçš„æµªè´¹ç”šè‡Ïx­»æœºã€‚但手工回收内存往往是一™å¹å¤æ‚è€Œè‰°å·¨çš„å·¥ä½œã€‚å› ä¸ø™¦é¢„å…ˆ¼‹®å®šå ç”¨çš„内存空间是å¦åº”该被回收是éžå¸¸å›°éš„¡š„åQ如果一ŒD늨‹åºä¸èƒ½å›žæ”¶å†…存空é—ß_¼Œè€Œä¸”在程åºè¿è¡Œæ—¶¾pÈ»Ÿä¸­åˆæ²¡æœ‰äº†å¯ä»¥åˆ†é…的内存½Iºé—´æ—Óž¼Œ˜q™æ®µ½E‹åºž®±åªèƒ½å´©æºƒã€?/p> <p>Javaå’ŒC++相比的优势在于,˜q™éƒ¨åˆ?垃圾"å¯ä»¥è¢«Java 虚拟机(JVMåQ‰ä¸­çš„一个程åºå‘çŽ°åÆˆè‡ªåŠ¨æ¸…é™¤æŽ‰ï¼Œè€Œä¸ç”¨ç¨‹åºå‘˜è‡ªå·±æƒ³ç€"delete"了ã€?/p> <p>Java语言æä¾›äº†ä¸€ä¸ªç³»¾lŸçñ”的线½E‹ï¼Œå›_žƒåœ¾æ”¶é›†å™¨¾U¿ç¨‹åQˆGarbage Collection ThreadåQ‰ï¼Œæ¥è·Ÿítªæ¯ä¸€å—分é…出åŽÈš„内存½Iºé—´åQŒå½“JVM处于½Iºé—²å¾ªçޝæ—Óž¼Œè‡ªåŠ¨å›žæ”¶æ¯ä¸€å—å¯ä»¥å›žæ”¶çš„内存ã€?/p> <p><strong>4.5.1.1 åžƒåœ¾å›žæ”¶å·¥ä½œæœºåˆ¶</strong></p> <p>垃圾攉™›†å™¨çº¿½E‹å®ƒæ˜¯ä¸€¿U低优先¾U§çš„¾U¿ç¨‹åQŒå®ƒå¿…须在一个Java½E‹åºçš„è¿è¡Œè¿‡½E‹ä¸­å‡ºçŽ°å†…å­˜½Iºé—²çš„æ—¶å€™æ‰åŽ»è¿›è¡Œå›žæ”¶å¤„ç†ã€?/p> <p>垃圾攉™›†å™¨ç³»¾lŸæœ‰å…¶åˆ¤æ–­å†…å­˜å—æ˜¯å¦éœ€è¦å›žæ”¶çš„判断标准的。垃圾收集器完全是自动被执行的,它ä¸èƒ½è¢«å¼ºåˆ¶æ‰§è¡ŒåQŒå³ä½¿ç¨‹åºå‘˜èƒ½æ˜Ž¼‹®åœ°åˆ¤æ–­å‡ºæŸä¸€å—内存应该被回收了,也ä¸èƒ½å¼ºåˆ¶æ‰§è¡Œåžƒåœ‘Ö›žæ”¶ç¨‹åºè¿›è¡Œåžƒåœ‘Ö›žæ”¶ã€?/p> <p>½E‹åºå‘˜å¯ä»¥åšçš„åªæœ‰è°ƒç”?System.gc()"æ?廸™®®"执行垃圾攉™›†å™¨ç¨‹åºï¼Œä½†æ˜¯˜q™ä¸ªåžƒåœ¾æ”‰™›†½E‹åºä»€ä¹ˆæ—¶å€™è¢«æ‰§è¡Œä»¥åŠæ˜¯å¦è¢«æ‰§è¡Œäº†åQŒéƒ½æ˜¯ä¸ä¸èƒ½æŽ§åˆ¶çš„。但是虽然垃圾收集器是低优先¾U§çš„¾U¿ç¨‹åQŒå´åœ¨ç³»¾lŸå†…å­˜å¯ç”¨é‡˜q‡ä½Žæ—Óž¼Œå®ƒä»ç„¶å¯èƒ½ä¼š½Hå‘åœ°æ‰§è¡Œæ¥æŒ½æ•‘¾pÈ»Ÿã€?/p> <p><strong>4.5.1.2 å“ªäº›½W¦åˆ"垃圾"标准</strong></p> <p>如果想了解JVM的垃圑֛žæ”Óž¼Œž®±å¿…™å»è¦çŸ¥é“JVM垃圾回收的标准ã€?/p> <p>垃圾攉™›†å™¨çš„"垃圾"标准åQšå¯¹è±¡å·²¾lä¸èƒ½è¢«½E‹åºä¸­çš„å…¶ä»–½E‹åºæ‰€å¼•用的时候,那么˜q™ä¸ªå¯¹è±¡çš„内存空间已¾l没有用了ã€?/p> <p>比如当一个方法执行完毕时åQŒåœ¨˜q™ä¸ªæ–ÒŽ³•中声明的对象ž®Þp¶…出其声明周期åQŒè¿™æ—¶å€™å°±å¯ä»¥è¢«å½“作垃圾收集了åQŒåªæœ‰å½“˜q™ä¸ªæ–ÒŽ³•被冋ơ被调用时æ‰ä¼šè¢«é‡æ–°åˆ›å¾ã€?/p> <p>例如åQ?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>……<br /> public void function(){<br /> OBJ obj=new OBJ();<br /> ……<br /> }<br /> ……<br /> </pre> </td> </tr> </tbody> </table> <p>å¦å¤–˜q˜å¯ä»¥å°†å¯¹è±¡çš„引用å˜é‡åˆå§‹åŒ–为nullå€û|¼Œä¹Ÿå¯ä»¥æ¥æš—示垃圾攉™›†å™¨æ¥æ”‰™›†è¯¥å¯¹è±¡ã€?/p> <p>例如åQ?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>……<br /> OBJ obj=new OBJ();<br /> Obj=null;<br /> ……<br /> </pre> </td> </tr> </tbody> </table> <p> </p> <p><strong>finalize()在该对象垃圾回收å‰è°ƒç”?/strong></p> <p>垃圾攉™›†å™¨è·Ÿítªæ¯ä¸€ä¸ªå¯¹è±¡ï¼ŒæŠŠé‚£äº›ä¸å¯åˆ°è¾„¡š„å¯¹è±¡å æœ‰çš„内存空间收集è“væ¥ï¼Œòq¶ä¸”在毋ơ进行垃圾收集之å‰ï¼Œåžƒåœ¾æ”‰™›†å™¨éƒ½ä¼šè°ƒç”¨ä¸€ä¸‹finalize()æ–ÒŽ³•。Java语言å…许½E‹åºå‘˜ç»™ä»ÖM½•对象æ·ÕdŠ finalize( )æ–ÒŽ³•åQŒä½†ä¹Ÿä¸èƒ½è¿‡åˆ†ä¾èµ–该æ–ÒŽ³•对系¾lŸèµ„æºçš„回收和å†åˆ©ç”¨åQŒå› ä¸ø™¿™ä¸ªæ–¹æ³•调用åŽçš„æ‰§è¡Œç»“果是ä¸å¯é¢„知的。对于ä“Q何给定对象,Java 虚拟机最多åªè°ƒç”¨ä¸€‹Æ? finalize æ–ÒŽ³•ã€?</p> <p>æˆ‘ä»¬ç”¨è¿™ä¸ªç¨‹åºæ¥æ¼”示一下:</p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class finalizeTest{<br /> public static void main( String[] args ){<br />  finalizeTest ft=new finalizeTest();<br />  ft.loading();<br />  byte bs[]=new byte[1450000];<br /> }<br /> public void loading(){<br />  test t=new test();<br />  t.callme();<br /> }<br /> }<br /> class test{<br /> protected void finalize(){<br /> System.out.println("call finalize");<br /> }<br /> public void callme(){<br /> System.out.println("callme");<br /> }<br /> }</pre> </td> </tr> </tbody> </table> 我们在命令行中键入如下命令:<br /> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>java -Xmx1k finalizeTest</pre> </td> </tr> </tbody> </table> ½E‹åº˜q行¾l“果如图 3 10所½Cºã€?br />                                        <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/113425571.jpg" alt="" border="0" /><br /> <p>˜q™æ—¶å€™ï¼Œæˆ‘们ž®†JVM所许å¯ä½¿ç”¨çš„æœ€å¤§å†…存设¾|®æˆ"1k"åQŒå½“å†…å­˜è¢«å æ»¡å‰JVM会首先去˜q›è¡Œå†…存回收åQŒäºŽæ˜¯å¤±åŽÀL´»åŠ¨çš„"test"对象被回æ”Óž¼Œåœ¨å›žæ”¶å‰è°ƒç”¨äº?finalize()"ã€?br /> </p> <p><strong>4.5.2 JVM垃圾回收的相关知è¯?/strong></p> <p>JVM使用的是分代垃圾回收的方å¼ï¼Œä¸»è¦æ˜¯å› ä¸ºåœ¨½E‹åº˜q行的时候会有如下特点:</p> <p>大多数对象在创å¾åŽå¾ˆå¿«å°±æ²¡æœ‰å¯¹è±¡ä½¿ç”¨å®ƒäº†ã€?/p> <p>大多数在一直被使用的对象很ž®‘å†åŽÕd¼•用新创å¾çš„对象ã€?/p> <p>å› æ­¤ž®±å°†Javaå¯¹è±¡åˆ†äØ“"òq´è½»"对象å’?òq´è€?对象åQŒJVMž®†å†…存堆åQˆHeapåQ‰åˆ†ä¸ÞZ¸¤ä¸ªåŒºåŸŸï¼Œä¸€ä¸ªæ˜¯"òq´è½»"区,å¦ä¸€ä¸ªæ˜¯"è€?区,Javaž®†è¿™ä¸¤ä¸ªåŒºåŸŸåˆ†åˆ«¿UîC½œæ˜?新生ä»?å’?è€ç”Ÿä»?ã€?/p> <p>"新生ä»?区域中,¾l大多数新创建的对象都存攑֜¨˜q™ä¸ªåŒºåŸŸé‡Œï¼Œæ­¤åŒºåŸŸä¸€èˆ¬æ¥è¯´è¾ƒž®è€Œä¸”垃圾回收频率较高åQŒåŒæ—¶å› ä¸?新生ä»?采用的算法和其存攄¡š„对象的特点,使该区域垃圾回收的效率也éžå¸¸é«˜ã€?/p> <p>è€?è€ç”Ÿä»?区域中存攄¡š„是在"新生ä»?中生存了较长旉™—´çš„对象,˜q™äº›å¯¹è±¡ž®†è¢«è½¬ç§»åˆ?è€ç”Ÿä»?区。这个区域一般è¦å¤§ä¸€äº›è€Œä¸”增长的速度相对äº?新生ä»?è¦æ…¢ä¸€äº›ï¼Œ"è€ç”Ÿä»?垃圾回收的执行频率也会低很多ã€?/p> <p>ç”׃ºŽJVM在垃圑֛žæ”¶å¤„ç†æ—¶ä¼šæ¶ˆè€—一定的¾pÈ»Ÿèµ„æºåQŒå› æ­¤æœ‰æ—¶å€™é€šè¿‡JVMå¯åŠ¨çš„æ—¶å€™æ·»åŠ ç›¸å…›_‚æ•°æ¥æŽ§åˆ¶"新生ä»?区域的大ž®ï¼Œæ¥è°ƒæ•´åžƒåœ‘Ö›žæ”¶å¤„ç†çš„频率éžå¸¸æœ‰ç”¨ã€‚以便于我们更åˆç†çš„利用¾pÈ»Ÿèµ„æºã€?/p> <p>"新生ä»?区域讄¡½®å‚æ•°æ˜?-Xmn"åQŒç”¨˜q™ä¸ªå‚æ•°å¯ä»¥åˆ¶å®š"新生ä»?区域的大ž®ã€?/p> <p>我们æ¥ä‹D一个例å­è¯´æ˜Žï¼š</p> <p>我们ž®Þq”¨¾pÈ»Ÿè‡ªå¸¦çš„程åºä½œä¸ÞZ¾‹å­ï¼Œåœ¨å‘½ä»¤è¡Œä¸Šé”®å…¥å¦‚下指令:</p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>CD C:"java"demo"jfc"SwingSet2[回èžR]<br /> C:"java"demo"jfc"SwingSet2>java -jar -verbose:gc<br /> -Xmn4m XX:+PrintGCDetails SwingSet2.jar[回èžR]<br /> </pre> </td> </tr> </tbody> </table> 上é¢åŠ å…¥äº†ä¸€ä¸ªæ–°çš„å‚æ•?XX:+PrintGCDetails"åQŒè¿™ä¸ªå‚数能够打å°å‡ºGC的详¾l†ä¿¡æ¯ã€‚å±òq•输出如下(节选)åQ?br /> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>[GC [DefNew: 3469K->84K(3712K), 0.0007778 secs] <br /> 23035K->19679K(28728K), 0.0009191 secs]<br /> [GC [DefNew: 3284K->171K(3712K), 0.0007283 secs] <br /> 22878K->19766K(28728K), 0.0008669 secs]<br /> [GC [DefNew: 3476K->260K(3712K), 0.0008504 secs] <br /> 23071K->19855K(28728K), 0.0009862 secs]<br /> [GC [DefNew: 3502K->87K(3712K), 0.0009267 secs] <br /> 23096K->19682K(28728K), 0.0010610 secs]</pre> </td> </tr> </tbody> </table> <p>我们需è¦è§£é‡Šä¸€ä¸‹è¾“å‡ºçš„è¯¦ç»†å†…å®¹çš„æ„æ€ï¼Œæ‹¿ç¬¬ä¸€è¡Œè¾“出æ¥è¯ß_¼š</p> <p>"DefNew: 3469K->84K(3712K), 0.0007778 secs"是指"新生ä»?的垃圑֛žæ”¶æƒ…况,˜q™é‡Œçš„æ„æ€æ˜¯ä»Žå ç”?469K内存½Iºé—´å˜äØ“84K内存½Iºé—´åQŒç”¨æ—?.0007778¿U’ã€?/p> <p>"23035K->19679K(28728K), 0.0009191 secs"是指æ€ÖM½“GC的回收情况,整体堆空间å ç”¨ä»Ž23035Ké™ä½Žåˆ?9679K的水òq»I¼Œç”¨æ—¶0.0009191¿U’ã€?/p> <p>那么åQŒè¿™æ—¶å€™æˆ‘们在ž®?新生ä»?的内存设ä¸?MåQŒåÆˆæŠŠå †çš„æœ€å¤§å¯æŽ§å€ÆD®¾å®šäØ“32MåQŒå†åŽÀL‰§è¡Œï¼Œé”®å…¥å¦‚下指ä×oåQ?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>java -jar -verbose:gc -Xmn8m -Xmx32m <br /> XX:+PrintGCDetails SwingSet2.jar[回èžR]</pre> </td> </tr> </tbody> </table> 得到的结果如下(节选)åQ?br /> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>[GC [DefNew: 6633K->6633K(7424K), 0.0000684 secs]<br /> [Tenured: 18740K->18820K(24576K), 0.0636505 secs] <br /> 25374K->18820K(32000K), 0.0639274 secs]<br /> [GC [DefNew: 6646K->6646K(7424K), 0.0002581 secs]<br /> [Tenured: 18820K->18884K(24576K), 0.0651957 secs] <br /> 25467K->18884K(32000K), 0.0658804 secs]<br /> [GC [DefNew: 6611K->6611K(7424K), 0.0000668 secs]<br /> [Tenured: 18884K->18505K(24576K), 0.0931406 secs] </pre> <pre>25496K->18505K(32000K), 0.0934295 secs]</pre> </td> </tr> </tbody> </table> <p><font face="楷体_GB2312">˜q™ä¸ª¾l“果说明åQ?/font></p> <p><font face="楷体_GB2312">"[DefNew: 6633K->6633K(7424K), 0.0000684 secs]"是指"新生ä»?的垃圑֛žæ”¶æƒ…况,˜q™é‡Œçš„æ„æ€æ˜¯ä»Žå ç”?633K内存½Iºé—´å˜äØ“6633K内存½Iºé—´åQŒç”¨æ—?. 0000684¿U’ã€?br /> "25374K->18820K(32000K), 0.0639274 secs"是指æ€ÖM½“GC的回收情况,整体堆空间å ç”¨ä»Ž25374Ké™ä½Žåˆ?8820K的水òq»I¼Œç”¨æ—¶0. 0639274¿U’ã€?br /> "[Tenured: 18740K->18820K(24576K), 0.0636505 secs]"是指"è€ç”Ÿä»?GC的回收情况,整体堆空间å ç”¨ä»Ž18740Ké™ä½Žåˆ?8820K的水òq»I¼Œç”¨æ—¶0.0009012¿U’ã€?/font></p> <p>通过˜q™äº›å‚数的调整我们å¯ä»¥çœ‹åˆ°åœ¨å¤„ç†åžƒåœ¾æ”‰™›†é—®é¢˜æ—Óž¼Œä»Žåžƒåœ‘Ö›žæ”¶çš„频率是时间方é¢çš„å˜åŒ–åQŒæˆ‘们å¯ä»¥æ ¹æ®ä¸åŒç¨‹åºçš„ä¸åŒæƒ…况予以调整ã€?/p> <p>æœ€åŽæœ‰å¿…è¦æä¸€ä¸‹GC的相兛_‚敎ͼš</p> <p><font face="楷体_GB2312">-XX:+PrintGCDetails 昄¡¤ºGC的详¾l†ä¿¡æ?br /> -XX:+PrintGCApplicationConcurrentTime 打å°åº”用执行的时é—?br /> -XX:+PrintGCApplicationStoppedTime 打å°åº”用被暂åœçš„æ—‰™—´<br /> 注:":"åŽçš„"+"寂¡¨½Cºå¼€å¯æ­¤é€‰é¡¹,如果æ˜?-"å·é‚£ä¹ˆè¡¨½Cºå…³é—­æ­¤é€‰é¡¹ã€?/font></p>  <br /> <img src ="http://m.tkk7.com/gen-sky/aggbug/285795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/gen-sky/" target="_blank">星期äº?/a> 2009-07-07 13:23 <a href="http://m.tkk7.com/gen-sky/articles/285795.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item><item><title>内存控制效率优化的寽C? 学习自《Java ½E‹åºå‘? 上ç­é‚£ç‚¹äº‹å„¿ã€?/title><link>http://m.tkk7.com/gen-sky/articles/285791.html</link><dc:creator>星期äº?/dc:creator><author>星期äº?/author><pubDate>Tue, 07 Jul 2009 05:19:00 GMT</pubDate><guid>http://m.tkk7.com/gen-sky/articles/285791.html</guid><wfw:comment>http://m.tkk7.com/gen-sky/comments/285791.html</wfw:comment><comments>http://m.tkk7.com/gen-sky/articles/285791.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/gen-sky/comments/commentRss/285791.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/gen-sky/services/trackbacks/285791.html</trackback:ping><description><![CDATA[å¯ç¤ºä¸€åQšStringå’ŒStringBufferçš„ä¸åŒä¹‹å¤?br /> <p>ç›æ€¿¡å¤§å®¶éƒ½çŸ¥é“Stringå’ŒStringBuffer之间是有区别的,但究竟它们之间到底区别在哪里åQŸæˆ‘们就冿œ¬ž®èŠ‚ä¸­ä¸€æŽ¢ç©¶ç«Ÿï¼Œçœ‹çœ‹èƒ½ç»™æˆ‘ä»¬äº›ä»€ä¹ˆå¯½Cºã€‚还是刚æ‰é‚£ä¸ªç¨‹åºï¼Œæˆ‘们把它改一改,ž®†æœ¬½E‹åºä¸­çš„String˜q›è¡Œæ— é™‹Æ¡çš„累加åQŒçœ‹çœ‹ä»€ä¹ˆæ—¶å€™æŠ›å‡ºå†…存超é™çš„异常åQŒç¨‹åºå¦‚下所½Cºï¼š</p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class MemoryTest{<br /> <br /> public static void main(String args[]){<br /> <br /> String s="abcdefghijklmnop";<br /> <br /> System.out.print("当å‰è™šæ‹Ÿæœºæœ€å¤§å¯ç”¨å†…å­˜äØ“:");<br /> <br /> System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br /> <br /> System.out.print("循环å‰ï¼Œè™šæ‹Ÿæœºå·²å ç”¨å†…å­˜:");<br /> <br /> System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> int count = 0;<br /> <br /> while(true){<br /> <br /> try{<br /> <br /> s+=s;<br /> <br /> count++;<br /> <br /> }<br /> <br /> catch(Error o){<br /> <br /> System.out.println("循环‹Æ¡æ•°:"+count);<br /> <br /> System.out.println("String实际字节æ•?"+s.length()/1024/1024+"M");<br /> <br /> System.out.print("循环åŽï¼Œå·²å ç”¨å†…å­?");<br /> <br /> System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> System.out.println("Catch到的错误:"+o);<br /> <br /> break;<br /> <br /> }<br /> <br /> }<br /> <br /> }<br /> <br /> }</pre> </td> </tr> </tbody> </table> ½E‹åº˜q行åŽï¼Œæžœç„¶ä¸ä¸€ä¼šå„¿çš„功夫就报出了异常,如图 3 3所½Cºã€?<br />                              <img alt="" src="http://m.tkk7.com/images/blogjava_net/gen-sky/111125320.jpg" width="512" height="262" /> <br /> <p>我们注æ„刎ͼŒåœ¨Stringçš„å®žé™…å­—èŠ‚æ•°åªæœ‰8M的情况下åQŒåó@环åŽå·²å å†…存数竟然已¾lè¾¾åˆîCº†63.56M。这说明åQŒString˜q™ä¸ªå¯¹è±¡çš„实际å ç”¨å†…存数é‡ä¸Žå…¶è‡ªíw«çš„字节æ•îC¸ç›¸ç¬¦ã€‚于是,在åó@çŽ?9‹Æ¡çš„æ—¶å€™å°±å·²ç»æŠ?OutOfMemoryError"的错误了ã€?/p> <p>å› æ­¤åQŒåº”该少用String˜q™ä¸œè¥¿ï¼Œç‰¹åˆ«æ˜? Stringçš?+="æ“作åQŒä¸ä»…原æ¥çš„String对象ä¸èƒ½¾l§ç®‹ä½¿ç”¨åQŒè€Œä¸”åˆè¦äº§ç”Ÿå¤šä¸ªæ–°å¯¹è±¡ï¼Œå› æ­¤ä¼šè¾ƒé«˜çš„å ç”¨å†…å­˜ã€?/p> <p>所以必™å»è¦æ”¹ç”¨StringBufferæ¥å®žçŽ°ç›¸åº”ç›®çš„ï¼Œä¸‹é¢æ˜¯æ”¹ç”¨StringBufferæ¥åšä¸€ä¸‹æµ‹è¯•:</p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class MemoryTest{<br /> <br /> public static void main(String args[]){<br /> <br /> StringBuffer s=new StringBuffer("abcdefghijklmnop");<br /> <br /> System.out.print("当å‰è™šæ‹Ÿæœºæœ€å¤§å¯ç”¨å†…å­˜äØ“:");<br /> <br /> System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br /> <br /> System.out.print("循环å‰ï¼Œè™šæ‹Ÿæœºå·²å ç”¨å†…å­˜:");<br /> <br /> System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> int count = 0;<br /> <br /> while(true){<br /> <br /> try{<br /> <br /> s.append(s);<br /> <br /> count++;<br /> <br /> }<br /> <br /> catch(Error o){<br /> <br /> System.out.println("循环‹Æ¡æ•°:"+count);<br /> <br /> System.out.println("String实际字节æ•?"+s.length()/1024/1024+"M");<br /> <br /> System.out.println("循环åŽï¼Œå·²å ç”¨å†…å­?");<br /> <br /> System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> System.out.println("Catch到的错误:"+o);<br /> <br /> break;<br /> <br /> }<br /> <br /> }<br /> <br /> }<br /> <br /> }</pre> </td> </tr> </tbody> </table> 我们ž®†Stringæ”¹äØ“StringBuffer以åŽåQŒåœ¨˜q行时得åˆîCº†å¦‚下¾l“æžœåQŒå¦‚å›? 3 4所½Cºã€?br />                             <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/111227471.jpg" alt="" border="0" /><br /> ˜q™æ¬¡æˆ‘们å‘现åQŒå½“StringBuffer所å ç”¨çš„实际字节数ä¸?16M"的时候æ‰äº§ç”Ÿæº¢å‡ºåQŒæ•´æ•´æ¯”上一个程åºçš„String实际字节æ•?8M"多了一å€ã€?br /> <p><strong>å¯ç¤º2åQšç”¨"-Xmx"傿•°æ¥æé«˜å†…å­˜å¯æŽ§åˆ¶é‡?/strong></p> <p>å‰é¢æˆ‘们介绘q?-Xmx"˜q™ä¸ªå‚数的用法,如果我们˜q˜æ˜¯å¤„ç†åˆšæ‰çš„那个用StringBufferçš„Java½E‹åºåQŒæˆ‘们用"-Xmx1024m"æ¥å¯åŠ¨å®ƒåQŒçœ‹çœ‹å®ƒçš„åó@环次数有什么å˜åŒ–ã€?/p> <p>输入如下指ä×oåQ?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>java -mx1024m MemoryTest</pre> </td> </tr> </tbody> </table> 得到¾l“果如图 3 5所½Cºã€?br />                             <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/111628142.jpg" alt="" border="0" /><br /> <p>那么通过使用"-Xmx"傿•°ž®†å…¶å¯æŽ§å†…å­˜é‡æ‰©å¤§è‡³1024MåŽï¼Œé‚£ä¹ˆ˜q™ä¸ª½E‹åºåˆîCº†1G的时候æ‰å†…å­˜­‘…é™åQŒä»Žè€Œä‹Éå†…å­˜çš„å¯æŽ§æ€§æé«˜äº†ã€?/p> <p>但扩大内存ä‹Éç”¨é‡æ°¸è¿œä¸æ˜¯æœ€¾lˆçš„解决æ–ÒŽ¡ˆåQŒå¦‚æžœä½ çš„ç¨‹åºæ²¡æœ‰åŽ»æ›´åŠ çš„ä¼˜åŒ–ï¼Œæ—©æ™š˜q˜æ˜¯ä¼šè¶…é™çš„ã€?/p> <p><strong>å¯ç¤º3åQšäºŒ¾l´æ•°¾l„比一¾l´æ•°¾l„å ç”¨æ›´å¤šå†…存空é—?/strong></p> <p>对于内存å ç”¨çš„问题还有一个地方值得我们注æ„åQŒå°±æ˜¯äºŒ¾l´æ•°¾l„的内存å ç”¨é—®é¢˜ã€?/p> <p>æœ‰æ—¶å€™æˆ‘ä»¬ä¸€åŽ¢æƒ…æ„¿çš„è®¤äØ“åQ?/p> <p>二维数组的å ç”¨å†…存空间多无鞞®±æ˜¯äºŒç»´æ•°ç»„的实际数¾l„元素数比一¾l´æ•°¾l„多而已åQŒé‚£ä¹ˆäºŒ¾l´æ•°¾l„的所å ç©ºé—ß_¼Œä¸€å®šæ˜¯å®žé™…甌™¯·çš„元素数而已ã€?/p> <p>但是åQŒäº‹å®žä¸Šòq¶ä¸æ˜¯è¿™æ ïLš„åQŒå¯¹äºŽä¸€ä¸ªäºŒ¾l´æ•°¾l„而言åQŒå®ƒæ‰€å ç”¨çš„内存空间覘qœè¿œå¤§äºŽå®ƒå¼€è¾Ÿçš„æ•°ç»„å…ƒç´ æ•°ã€‚ä¸‹é¢æˆ‘们æ¥çœ‹ä¸€ä¸ªä¸€¾l´æ•°¾l„程åºçš„例å­åQ?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class MemFor{<br /> <br /> public static void main (String[] args) {<br /> <br /> try{<br /> <br /> int len=1024*1024*2;   //讑֮šå¾ªçޝ‹Æ¡æ•°<br /> <br /> byte [] abc=new byte[len];<br /> <br /> for (int i=0;i<len;i++){<br /> <br /> abc[i]=(byte)i;<br /> <br /> }<br /> <br /> System.out.print("å·²å ç”¨å†…å­?"); <br /> <br /> System.out.println(<br /> <br /> Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> }<br /> <br /> catch(Error e){<br /> <br /> }<br /> <br /> }<br /> <br /> }</pre> </td> </tr> </tbody> </table> ˜q™ä¸ª½E‹åºæ˜¯å¼€è¾Ÿäº†"1024*1024*2"å?M的数¾l„元素的一¾l´æ•°¾l„,˜q行˜q™ä¸ª½E‹åºå¾—到的结果如å›? 3 6所½Cºï¼Œ½E‹åº˜q行¾l“æžœæç¤º"å·²å ç”¨å†…存:3M"ã€?br />                                        <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/111832715.jpg" alt="" border="0" /> <br /> <br /> <br /> <p>我们å†å°†˜q™ä¸ª½E‹åº˜q›è¡Œä¿®æ”¹åQŒæ”¹ä¸ÞZ¸€ä¸ªäºŒ¾l´æ•°¾l„,˜q™ä¸ªäºŒç»´æ•°ç»„çš„å…ƒç´ æ•°é‡æˆ‘们也ž®½é‡çš„和上一个一¾l´æ•°¾l„的元素数é‡ä¿æŒä¸€è‡´ã€?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class MemFor{<br /> <br /> public static void main (String[] args) {<br /> <br /> try{<br /> <br /> int len=1024*1024;  //讑֮šå¾ªçޝ‹Æ¡æ•°<br /> <br /> byte [][] abc=new byte[len][2];<br /> <br /> for (int i=0;i<len;i++){<br /> <br /> abc[i][0]=(byte)i;<br /> <br /> abc[i][1]=(byte)i;<br /> <br /> }<br /> <br /> System.out.print("å·²å ç”¨å†…å­?"); <br /> <br /> System.out.println(<br /> <br /> Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> }<br /> <br /> catch(Error e){<br /> <br /> }<br /> <br /> }<br /> <br /> }<br /> <br /> </pre> </td> </tr> </tbody> </table> 当我们把甌™¯·çš„å…ƒç´ æ•°é‡æœªå˜ï¼Œåªæ˜¯ž®†äºŒ¾l´æ•°¾l„çš„è¡Œæ•°å®šäØ“"1024*1024"åˆ—æ•°å®šäØ“"2"åQŒå’Œåˆšæ‰çš„那个一¾l´æ•°¾l?1024*1024*2"的数é‡å®Œå…¨ä¸€è‡ß_¼Œä½†æˆ‘们得到的˜qç®—¾l“果如图 3 7所½Cºï¼Œç«Ÿç„¶å ç”¨è¾‘Öˆ°äº?9M的空间ã€?br />                                      <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/111922889.jpg" alt="" border="0" /><br /> 我们姑且ä¸ç®¡é€ æˆ˜q™ç§æƒ…况的原因,我们åªè¦çŸ¥é“一点就够了åQŒé‚£ž®±æ˜¯"二维数组å å†…å­?。所以,在编写程åºçš„æ—¶å€™è¦æ³¨æ„åQŒèƒ½ä¸ç”¨äºŒç»´æ•°ç»„的地方尽é‡ç”¨ä¸€¾l´æ•°¾l„ï¼Œè¦æ±‚内存å ç”¨ž®çš„地方ž®½é‡ç”¨ä¸€¾l´æ•°¾l„ã€?br /> <br /> <br /> <br /> <br /> <p><strong>4.4.4 å¯ç¤º4åQšç”¨HashMapæé«˜å†…存查询速度</strong></p> <p><strong>田富é¹ä¸»¾~–的《大学计½Ž—机应用基础》中是这æ äh˜q°å†…存的åQ?/strong></p> <p><font face="楷体_GB2312">……</font></p> <p><font face="楷体_GB2312">DRAMåQšå³å†…å­˜æ¡ã€‚常说的内存òq¶ä¸æ˜¯å†…部存储器åQŒè€Œæ˜¯DRAMã€?/font></p> <p><font face="楷体_GB2312">……CPUçš„è¿è¡Œé€Ÿåº¦å¾ˆå¿«åQŒè€Œå¤–部存储器的读å–速度相对æ¥è¯´ž®±å¾ˆæ…¢ï¼Œå¦‚æžœCPU需è¦ç”¨åˆ°çš„æ•°æ®æ€ÀL˜¯ä»Žå¤–部存储器中读å–,ç”׃ºŽå¤–部讑֤‡å¾ˆæ…¢åQ?#8230;…åQŒCPUå¯èƒ½ç”¨åˆ°çš„æ•°æ®é¢„先读到DRAM中,CPU产生的äÍæ—¶æ•°æ®ä¹Ÿæš‚时存放在DRAM中,˜q™æ ·çš„结果是大大的æé«˜äº†CPU的利用率和计½Ž—机˜q行速度ã€?/font></p> <p><font face="楷体_GB2312">……</font></p> <p>˜q™æ˜¯ä¸€ä¸ªå…¸åž‹è®¡½Ž—机基础教æé’ˆå¯¹å†…存的æ˜qŽÍ¼Œä¹Ÿè®¸ä½œäؓ计算æœÞZ¸“业的½E‹åºå‘˜å¯¹˜q™æ®µæè¿°òq¶ä¸é™Œç”Ÿã€‚ä½†ä¹Ÿå› ä¸ø™¿™ŒD‰|˜qŽÍ¼Œè€Œå¯¹å†…存的处ç†é€Ÿåº¦æœ‰ç¥žè¯çš„ç†è§£åQŒè®¤ä¸ºå†…存中的处ç†é€Ÿåº¦æ˜¯éžå¸¸å¿«çš„ã€?/p> <p>以ä‹ÉæŒæœ‰˜q™ç§è§‚点的程åºå‘˜é‡åˆ°ä¸€ä¸ªå·¨åž‹çš„内存查询循环的较长时间时åQŒè€ŒæŸæ‰‹æ— ½{–了ã€?/p> <p><strong>è¯ïLœ‹ä¸€ä¸‹å¦‚下程åºï¼š</strong></p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class MemFor{<br /> <br /> public static void main (String[] args) {<br /> <br /> long start=System.currentTimeMillis(); //å–得当剿—‰™—´<br /> <br /> int len=1024*1024*3;   //讑֮šå¾ªçޝ‹Æ¡æ•°<br /> <br /> int [][] abc=new int[len][2];<br /> <br /> for (int i=0;i<len;i++){<br /> <br /> abc[i][0]=i;<br /> <br /> abc[i][1]=(i+1);<br /> <br /> }<br /> <br /> long get=System.currentTimeMillis();  //å–得当剿—‰™—´<br /> <br /> //循环ž®†æƒ³è¦çš„æ•°å€¼å–出æ¥åQŒæœ¬½E‹åºå–æ•°¾l„的最åŽä¸€ä¸ªå€?br /> <br /> for (int i=0;i<len;i++){<br /> <br /> if ((int)abc[i][0]==(1024*1024*3-1)){<br /> <br /> System.out.println("å–值结æž?"+abc[i][1]);<br /> <br /> }<br /> <br /> }<br /> <br /> long end=System.currentTimeMillis();   //å–得当剿—‰™—´<br /> <br /> //输出‹¹‹è¯•¾l“æžœ<br /> <br /> System.out.println("赋值åó@环时é—?"+(get-start)+"ms");<br /> <br /> System.out.println("获å–循环旉™—´:"+(end-get)+"ms");<br /> <br /> System.out.print("Javaå¯æŽ§å†…å­˜:");<br /> <br /> System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br /> <br /> System.out.print("å·²å ç”¨å†…å­?");<br /> <br /> System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> }<br /> <br /> }</pre> </td> </tr> </tbody> </table> ˜q行˜q™ä¸ª½E‹åºåQ? <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>java -Xmx1024m MemFor<br /> <br /> </pre> </td> </tr> </tbody> </table> <p><strong>½E‹åºçš„è¿è¡Œç»“果如下:</strong></p> <p>å–值结æž?3145728</p> <p>赋值åó@环时é—?2464ms</p> <p>获å–循环旉™—´:70ms</p> <p>Javaå¯æŽ§å†…å­˜:1016M</p> <p>å·²å ç”¨å†…å­?128M</p> <p>我们å‘现åQŒè¿™ä¸ªç¨‹åºåó@环了3145728‹Æ¡èŽ·å¾—æƒ³è¦çš„¾l“æžœåQŒåó@çŽ¯èŽ·å–æ•°å€¼çš„æ—‰™—´ç”¨äº†70毫秒ã€?/p> <p><font face="楷体_GB2312">你觉得快å—?</font></p> <p><font face="楷体_GB2312">是啊åQ?0毫秒虽然ž®äºŽ1¿U’é’ŸåQŒä½†æ˜¯å¦‚果你ä¸å¾—ä¸åœ¨˜q™ä¸ªå¾ªçޝ外é¢å†å¥—一个åó@环,å³ä‹É外层嵌套的åó@çŽ¯åªæœ?00‹Æ¡ï¼Œé‚£ä¹ˆåQŒæƒ³æƒ³çœ‹æ˜¯å¤šž®‘毫¿U’å‘¢åQ?/font></p> <p><font face="楷体_GB2312">回答åQ?0毫秒*100=7000毫秒=7¿U?/font></p> <p><font face="楷体_GB2312">如果åQŒåó@çŽ?000‹Æ¡å‘¢åQ?/font></p> <p><font face="楷体_GB2312">70¿U’ï¼</font></p> <p><font face="楷体_GB2312">70¿U’çš„˜q行旉™—´å¯¹äºŽ˜q™ä¸ª½E‹åºæ¥è¯´ž®±æ˜¯çùNš¾äº†ã€?br /> </font> <br /> é¢å¯¹˜q™ä¸ª½E‹åºçš„è¿è¡Œæ—¶é—´å¾ˆå¤šç¨‹åºå‘˜å·²ç»æŸæ‰‹æ— ç­–了,其实åQŒJava¾l™ç¨‹åºå‘˜ä»¬æä¾›äº†ä¸€ä¸ªè¾ƒå¿«çš„æŸ¥è¯¢æ–ÒŽ³•--哈希表查询ã€?/p> <p>我们ž®†è¿™ä¸ªç¨‹åºç”¨"HashMap"æ¥æ”¹é€ ä¸€ä¸‹ï¼Œå†çœ‹çœ‹è¿è¡Œç»“果:</p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>import java.util.*;<br /> <br /> public class HashMapTest{<br /> <br /> public static void main (String[] args) {<br /> <br /> HashMap has=new HashMap();<br /> <br /> int len=1024*1024*3;<br /> <br /> long start=System.currentTimeMillis();<br /> <br /> for (int i=0;i<len;i++){<br /> <br /> has.put(""+i,""+i);<br /> <br /> }<br /> <br /> long end=System.currentTimeMillis();<br /> <br /> System.out.println("å–值结æž?"+has.get(""+(1024*1024*3-1)));<br /> <br /> long end2=System.currentTimeMillis();<br /> <br /> System.out.println("赋值åó@环时é—?"+(end-start)+"ms");<br /> <br /> System.out.println("获å–循环旉™—´:"+(end2-end)+"ms");<br /> <br /> System.out.print("Javaå¯æŽ§å†…å­˜:");<br /> <br /> System.out.println(Runtime.getRuntime().maxMemory()/1024/1024+"M");<br /> <br /> System.out.print("å·²å ç”¨å†…å­?");<br /> <br /> System.out.println(Runtime.getRuntime().totalMemory()/1024/1024+"M");<br /> <br /> }<br /> <br /> }</pre> </td> </tr> </tbody> </table> <strong>˜q行˜q™ä¸ª½E‹åºåQ?/strong><br /> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>java -Xmx1024m HashMapTest</pre> </td> </tr> </tbody> </table> <p><strong>½E‹åºçš„è¿è¡Œç»“果如下:</strong></p> <p>å–之¾l“æžœ:3145727</p> <p>赋值åó@环时é—?16454ms</p> <p>获å–循环旉™—´:0ms</p> <p>Javaå¯æŽ§å†…å­˜:1016M</p> <p>å·²å ç”¨å†…å­?566M</p> <p>那么现在用HashMapæ¥å–值的旉™—´ç«Ÿç„¶ä¸åˆ°1msåQŒè¿™æ—¶æˆ‘们的½E‹åºçš„æ•ˆçŽ‡æ˜Žæ˜¾æé«˜äº†åQŒçœ‹æ¥ç”¨å“ˆå¸Œè¡¨è¿›è¡Œå†…å­˜ä¸­çš„æ•°æ®æœç´¢é€Ÿåº¦¼‹®å®žå¾ˆå¿«ã€?/p> <p>在æé«˜æ•°æ®æœç´¢é€Ÿåº¦çš„åŒæ—¶ä¹Ÿè¦æ³¨æ„到åQŒèµ‹å€¼æ—¶é—´çš„差异和内存å ç”¨çš„差异ã€?/p> <p><strong>赋值åó@环时é—ß_¼š</strong></p> <p>HashMapåQ?6454ms</p> <p>普通数¾l„:2464ms</p> <p>å ç”¨å†…å­˜åQ?/p> <p>HashMapåQ?66M</p> <p>普通数¾l„:128M</p> <p>å› æ­¤åQŒå¯ä»¥çœ‹å‡ºHashMap在åˆå§‹åŒ–以åŠå†…å­˜å ç”¨æ–šw¢éƒ½è¦é«˜äºŽæ™®é€šæ•°¾l„ï¼Œå¦‚æžœä»…ä»…æ˜¯äØ“äº†æ•°æ®å­˜å‚¨ï¼Œç”¨æ™®é€šæ•°¾l„是比较适åˆçš„,但是åQŒå¦‚æžœäØ“äº†é¢‘¾J查询的目的åQŒHashMap是必然的选择ã€?br /> </p> <p><strong>å¯ç¤º5åQšç”¨"arrayCopy()"æé«˜æ•°ç»„截å–速度</strong></p> <p>当我们需è¦å¤„ç†ä¸€ä¸ªå¤§çš„æ•°¾l„应用时往往需è¦å¯¹æ•°ç»„˜q›è¡Œå¤§é¢¿U¯æˆªå–与å¤åˆ¶æ“作åQŒæ¯”如针对图形显½Cºçš„应用时啾U¯çš„通过å¯ÒŽ•°¾l„å…ƒç´ çš„å¤„ç†æ“作有时æ‰è¥Ÿè§è‚˜ã€?/p> <p>æé«˜æ•°ç»„处ç†é€Ÿåº¦çš„一个很好的æ–ÒŽ³•æ˜?System.arrayCopy()"åQŒè¿™ä¸ªæ–¹æ³•å¯ä»¥æé«˜æ•°¾l„的截å–速度åQŒæˆ‘们å¯ä»¥åšä¸€ä¸ªå¯¹æ¯”试验ã€?/p> <p>例如我们用普通的数组赋值方法æ¥å¤„熽E‹åºå¦‚下åQ?/p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public class arraycopyTest1{<br /> <br /> public static void main( String[] args ){<br /> <br /> String temp="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";<br /> <br /> char[] oldArray=temp.toCharArray();<br /> <br /> char[] newArray=null;<br /> <br /> long start=0L;<br /> <br /> newArray=new char[length]; <br /> <br /> //开始时间记å½?br /> <br /> start=System.currentTimeMillis();<br /> <br /> for(int i=0;i<10000000;i++){<br /> <br /> for(int j=0;j<length;j++){<br /> <br /> newArray[j]=oldArray[begin+j];<br /> <br /> }<br /> <br /> }<br /> <br /> //æ‰“å°æ€È”¨æ—‰™—´<br /> <br /> System.out.println(System.currentTimeMillis()-start+"ms");<br /> <br /> }<br /> <br /> }<br /> <br /> </pre> </td> </tr> </tbody> </table> ½E‹åº˜q行¾l“果如图 3 8所½Cºã€?br />                               <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/1126040.jpg" alt="" border="0" /><br /> <br /> é‚£ä¹ˆä¸‹é¢æˆ‘们å†ç”¨arrayCopy()的方法试验一下:<br /> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre>public final class arraycopyTest2{<br /> <br /> public static void main( String[] args ){<br /> <br /> String temp="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"<br /> <br /> +"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";<br /> <br /> char[] oldArray=temp.toCharArray(); <br /> <br /> char[] newArray=null; <br /> <br /> long start=0L; <br /> <br /> newArray=new char[length]; <br /> <br /> //记录开始时é—?br /> <br /> start=System.currentTimeMillis(); <br /> <br /> for(int i=0;i<10000000;i++ ){<br /> <br /> System.arraycopy(oldArray,100,newArray,0,120);<br /> <br /> }<br /> <br /> //æ‰“å°æ€È”¨æ—‰™—´<br /> <br /> System.out.println((System.currentTimeMillis()-start)+"ms");<br /> <br /> }<br /> <br /> }<br /> <br /> </pre> </td> </tr> </tbody> </table> <p>½E‹åº˜q行¾l“果如图 3 9所½Cºã€?/p> <p>                         <img src="http://m.tkk7.com/images/blogjava_net/gen-sky/1126041.jpg" alt="" border="0" /><br /> </p> <br /> <p>两个½E‹åºçš„å·®è·å†3¿U’多åQŒå¦‚æžœå¤„ç†æ›´å¤§æ‰¹é‡çš„æ•°ç»„他们的差è·è¿˜ä¼šæ›´å¤§ï¼Œå› æ­¤åQŒå¯ä»¥åœ¨é€‚当的情况下用这个方法æ¥å¤„ç†æ•°ç»„的问题ã€?/p> <p>æœ‰æ—¶å€™æˆ‘ä»¬äØ“äº†ä‹É用方便,å¯ä»¥åœ¨è‡ªå·Þqš„tools包中é‡è²ä¸€ä¸ªarrayCopyæ–ÒŽ³•åQŒå¦‚下:</p> <table bordercolordark="#ffffff" bordercolorlight="black" width="400" align="center" border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td bgcolor="#e6e6e6"> <pre> public static Object[] arrayCopy(int pos,Object[] srcObj){<br /> <br /> return arrayCopy(pos,srcObj.length,srcObj);<br /> <br /> }<br /> <br /> public static Object[] arrayCopy(int pos,int dest,Object[] srcObject){<br /> <br /> Object[] rv=null;<br /> <br /> rv=new Object[dest-pos];<br /> <br /> System.arraycopy(srcObject,pos,rv,0,rv.length);<br /> <br /> return rv;<br /> <br /> }</pre> </td> </tr> </tbody> </table> <br /> <img src ="http://m.tkk7.com/gen-sky/aggbug/285791.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/gen-sky/" target="_blank">星期äº?/a> 2009-07-07 13:19 <a href="http://m.tkk7.com/gen-sky/articles/285791.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item><item><title>java和内存有关系 ------------------- 学习自《Java½E‹åºå‘?上ç­é‚£ç‚¹äº‹å„¿ã€?/title><link>http://m.tkk7.com/gen-sky/articles/285787.html</link><dc:creator>星期äº?/dc:creator><author>星期äº?/author><pubDate>Tue, 07 Jul 2009 04:38:00 GMT</pubDate><guid>http://m.tkk7.com/gen-sky/articles/285787.html</guid><wfw:comment>http://m.tkk7.com/gen-sky/comments/285787.html</wfw:comment><comments>http://m.tkk7.com/gen-sky/articles/285787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/gen-sky/comments/commentRss/285787.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/gen-sky/services/trackbacks/285787.html</trackback:ping><description><![CDATA[     摘è¦: 堆和æ ?  栈与堆都是Java用æ¥åœ¨å†…存中存放数æ®çš„地æ–V€?  A.å ?-用new建立åQŒåžƒåœ¾è‡ªåŠ¨å›žæ”¶è´Ÿè´£å›žæ”?     1ã€å †æ˜¯ä¸€ä¸?˜q行æ—?æ•°æ®åŒºï¼Œ¾cÕd®žä¾‹åŒ–的对象就是从堆上åŽÕdˆ†é…空间的åQ?     2ã€åœ¨å †ä¸Šåˆ†é…½Iºé—´æ˜¯é€šè¿‡"new"½{‰æŒ‡ä»¤å¾ç«‹çš„åQ?   &n...  <a href='http://m.tkk7.com/gen-sky/articles/285787.html'>阅读全文</a><img src ="http://m.tkk7.com/gen-sky/aggbug/285787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/gen-sky/" target="_blank">星期äº?/a> 2009-07-07 12:38 <a href="http://m.tkk7.com/gen-sky/articles/285787.html#Feedback" target="_blank" style="text-decoration:none;">å‘表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>¸ÐлÄú·ÃÎÊÎÒÃǵÄÍøÕ¾£¬Äú¿ÉÄÜ»¹¶ÔÒÔÏÂ×ÊÔ´¸ÐÐËȤ£º</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> Ö÷Õ¾Ö©Öë³ØÄ£°å£º <a href="http://sdbfgcjx.com" target="_blank">ÍáÍáÂþ»­ÔÚÏß¹Û¿´¹ÙÍøÃâ·ÑÔĶÁ</a>| <a href="http://222dv.com" target="_blank">ÑÇÖÞ¹ú²ú¾«Æ·ÎÞÂë¾Ã¾Ã¾Ã¾Ã¾ÃÔ»</a>| <a href="http://www2626cf.com" target="_blank">¾Ã¾Ã¾«Æ·¹ú²úÑÇÖÞavÌìÃÀ18</a>| <a href="http://tttui.com" target="_blank">ÑÇÖÞÎÞÂ뾫ƷÀ˳±</a>| <a href="http://222xx8.com" target="_blank">13Ò»14ÖÜËêëƬÃâ·Ñ</a>| <a href="http://ikybh.com" target="_blank">³ÉÈËÑÇÖÞ¹ú²ú¾«Æ·¾Ã¾Ã</a>| <a href="http://ahbbht.com" target="_blank">ÑÇÖÞavÎÞÂë³±ÅçÔÚÏß¹Û¿´</a>| <a href="http://xyyfamily.com" target="_blank">¹ú²ú¾«Æ·³ÉÈËÃâ·ÑÊÓÆµÍøÕ¾¾©¶« </a>| <a href="http://pyjxyey.com" target="_blank">ÑÇÖÞ¸ßÇå×¨ÇøÈÕº«¾«Æ·</a>| <a href="http://sk7758.com" target="_blank">ÔÚÏß¹Û¿´ÈÕ±¾Ãâ·Ña¡ÅÊÓÆµ</a>| <a href="http://xin-matai.com" target="_blank">δÂúÊ®°Ë˽È˸ßÇåÃâ·ÑÓ°Ôº</a>| <a href="http://zhxydq.com" target="_blank">ÑÇÖÞÒ»Çø¶þÇøÔÚÏßÃâ·Ñ¹Û¿´</a>| <a href="http://952268.com" target="_blank">ËÄ»¢Ó°ÊÓÔÚÏßÓÀ¾ÃÃâ·Ñ¹Û¿´</a>| <a href="http://km9c.com" target="_blank">91ÀÏʪ»ú¸£ÀûÃâ·ÑÌåÑé</a>| <a href="http://jhc2go.com" target="_blank">¿´³ÉÄêÅ®ÈËÃâ·ÑÎçÒ¹ÊÓÆµ</a>| <a href="http://cndianxian.com" target="_blank">Âé¶¹ÑÇÖÞavÊìÅ®¹ú²úÒ»Çø¶þ</a>| <a href="http://xyjxnhcl.com" target="_blank">Ãâ·ÑÈ˳ÉÎÞÂë´óƬÔÚÏß¹Û¿´</a>| <a href="http://xiamenwave.com" target="_blank">ÔÚÏßÃâ·ÑÖÐÎÄ×ÖÄ»</a>| <a href="http://abc17171.com" target="_blank">ÑÇÖÞÃâ·ÑÒ»Çø¶þÇø</a>| <a href="http://www-15706.com" target="_blank">ÑÇÖÞ¸ßÇåÖÐÎÄ×ÖÄ»Ãâ·Ñ</a>| <a href="http://sqmdjz.com" target="_blank">¾Ã¾Ã¾«Æ·¹ú²úÑÇÖÞ</a>| <a href="http://78avai.com" target="_blank">ҹɫ¸óÑÇÖÞÒ»Çø¶þÇøÈýÇø</a>| <a href="http://927ff.com" target="_blank">hÔÚÏß¿´Ãâ·ÑÊÓÆµÍøÕ¾ÄÐÄÐ</a>| <a href="http://tskes.com" target="_blank">¹úÄÚ¾«Æ·Ãâ·ÑÂé¶¹ÍøÕ¾91Âé¶¹</a>| <a href="http://xxxxnii.com" target="_blank">ÌìÌìÅÄÅÄÌìÌìˬÃâ·ÑÊÓÆµ</a>| <a href="http://6363388.com" target="_blank">Ò»¸öÈË¿´µÄÃâ·Ñ¹Û¿´ÈÕ±¾ÊÓÆµwww</a>| <a href="http://lcqkp.com" target="_blank">2022ÄêÑÇÖÞÎçÒ¹Ò»Çø¶þÇø¸£Àû </a>| <a href="http://haohaoshuo.com" target="_blank">ÑÇÖÞÂÒÂë¹ú²úÂÒÂ뾫»ª</a>| <a href="http://69xjk.com" target="_blank">ÑÇÖÞ¹ú²ú¾«Æ·lv</a>| <a href="http://zhuanjiao521.com" target="_blank">ÑÇÖÞAVÒÁÈ˾þÃÇàÇà²ÝÔ­</a>| <a href="http://1000hu.com" target="_blank">Ò»¸öÈËÔÚÏß¹Û¿´ÊÓÆµÃâ·Ñ</a>| <a href="http://831055.com" target="_blank">¾Ã¾ÃÎçÒ¹ÎÞÂëÃâ·Ñ</a>| <a href="http://600c28.com" target="_blank">ÎåÔÂÌì¹ú²ú³ÉÈËAVÃâ·Ñ¹Û¿´</a>| <a href="http://988938.com" target="_blank">ÑÇÖÞÈ˳ɵçÓ°ÍøÕ¾¾Ã¾Ã</a>| <a href="http://wilbysec.com" target="_blank">ÑÇÖÞÊÓÆµÃâ·ÑÒ»Çø</a>| <a href="http://zbr555sina.com" target="_blank">ÑÇÖÞžžAVÎÞÂëÆ¬</a>| <a href="http://lidajc.com" target="_blank">¹ú²ú¾«Æ·ÑÇÖÞÃÀÅ®¾Ã¾Ã¾Ã</a>| <a href="http://mp4888.com" target="_blank">¹ú²ú¾«Æ·ÄÛ²ÝÓ°ÔºÃâ·Ñ</a>| <a href="http://yimintech.com" target="_blank">¹ú²úv¾«Æ·³ÉÈËÃâ·ÑÊÓÆµ400Ìõ</a>| <a href="http://123470c.com" target="_blank">Ò»¼¶Ã«Æ¬**²»¿¨Ãâ·Ñ²¥</a>| <a href="http://wwwdd312.com" target="_blank">¶¡Ï㻨ÔÚÏß¹Û¿´Ãâ·Ñ¹Û¿´Í¼Æ¬ </a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>