﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-T9的空间 -随笔分类-Useful information</title><link>http://www.cppblog.com/xieshuo/category/8227.html</link><description>You will never walk alone!</description><language>zh-cn</language><lastBuildDate>Wed, 03 Aug 2016 02:52:51 GMT</lastBuildDate><pubDate>Wed, 03 Aug 2016 02:52:51 GMT</pubDate><ttl>60</ttl><item><title>Linux memory summary</title><link>http://www.cppblog.com/xieshuo/archive/2013/12/09/204679.html</link><dc:creator> Torres</dc:creator><author> Torres</author><pubDate>Mon, 09 Dec 2013 09:42:00 GMT</pubDate><guid>http://www.cppblog.com/xieshuo/archive/2013/12/09/204679.html</guid><wfw:comment>http://www.cppblog.com/xieshuo/comments/204679.html</wfw:comment><comments>http://www.cppblog.com/xieshuo/archive/2013/12/09/204679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xieshuo/comments/commentRss/204679.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xieshuo/services/trackbacks/204679.html</trackback:ping><description><![CDATA[<span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">From Unix某论坛，忘记名字了...但这段文字从宏观上讲清楚了Linux Memory的构架。<br />1. </span><span style="font-size: 10.5pt; font-family: 宋体;">内核初始化：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">内核建立好内核页目录页表数据库，假设物理内存大小为</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">len</span><span style="font-size: 10.5pt; font-family: 宋体;">，则建立了</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">[3G--3G+len]::[0--len]</span><span style="font-size: 10.5pt; font-family: 宋体;">这样的虚地址</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">和物理地址</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">paddr</span><span style="font-size: 10.5pt; font-family: 宋体;">的线性对应关系；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">内核建立一个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">数组，</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">数组和物理页面系列完全是线性对应，</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">用来管理该物理页面状态，每个物理页面的虚地址保存在</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page-&gt;virtual</span><span style="font-size: 10.5pt; font-family: 宋体;">中；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">内核建立好一个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">，将没有使用的物理页面对应的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">放入其中，已经使用的就不用放入了；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> 2. </span><span style="font-size: 10.5pt; font-family: 宋体;">内核模块申请内存</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr = get_free_pages(mask,order)</span><span style="font-size: 10.5pt; font-family: 宋体;">：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">内存管理模块从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">找到一个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">，将</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page-&gt;virtual</span><span style="font-size: 10.5pt; font-family: 宋体;">作为返回值，该返回值就是对应物理页面的虚地址；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">将</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">中脱离；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">模块使用该虚拟地址操作对应的物理内存；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> 3. </span><span style="font-size: 10.5pt; font-family: 宋体;">内核模块使用</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">，例如执行指令</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">mov(eax, vaddr)</span><span style="font-size: 10.5pt; font-family: 宋体;">：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * CPU</span><span style="font-size: 10.5pt; font-family: 宋体;">获得</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">这个虚地址，利用建立好的页目录页表数据库，找到其对应的物理内存地址；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">将</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">eax</span><span style="font-size: 10.5pt; font-family: 宋体;">的内容写入</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的物理内存地址内；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> 4. </span><span style="font-size: 10.5pt; font-family: 宋体;">内核模块释放内存</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_pages(vaddr,order)</span><span style="font-size: 10.5pt; font-family: 宋体;">：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">依据</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">找到对应的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">将该</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">加入到</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">中；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> 5. </span><span style="font-size: 10.5pt; font-family: 宋体;">用户进程申请内存</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr = malloc(size)</span><span style="font-size: 10.5pt; font-family: 宋体;">：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">内存管理模块从用户进程内存空间</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">(0--3G)</span><span style="font-size: 10.5pt; font-family: 宋体;">中找到一块还没使用的空间</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vm_area_struct(start--end)</span><span style="font-size: 10.5pt; font-family: 宋体;">；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">随后将其插入到</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">task-&gt;mm-&gt;mmap</span><span style="font-size: 10.5pt; font-family: 宋体;">链表中；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> 6. </span><span style="font-size: 10.5pt; font-family: 宋体;">用户进程写入</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr(0-3G)</span><span style="font-size: 10.5pt; font-family: 宋体;">，例如执行指令</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">mov(eax, vaddr)</span><span style="font-size: 10.5pt; font-family: 宋体;">：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * CPU</span><span style="font-size: 10.5pt; font-family: 宋体;">获得</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">这个虚地址，该虚地址应该已经由</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">glibc</span><span style="font-size: 10.5pt; font-family: 宋体;">库设置好了，一定在</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">3G</span><span style="font-size: 10.5pt; font-family: 宋体;">一下的某个区域，根据</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">CR3</span><span style="font-size: 10.5pt; font-family: 宋体;">寄存器指向的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">current-&gt;pgd</span><span style="font-size: 10.5pt; font-family: 宋体;">查当前进程的页目录页表数据库，发现该</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的页目录表项为</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">0</span><span style="font-size: 10.5pt; font-family: 宋体;">，故产生异常；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">在异常处理中，发现该</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vm_area_struct</span><span style="font-size: 10.5pt; font-family: 宋体;">已经存在，为</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的页目录表项分配一个页表；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">随后从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">找到一个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">，将该</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的物理页面物理首地址赋给</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的页表表项，很明显，此时的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">paddr</span><span style="font-size: 10.5pt; font-family: 宋体;">不是线性对应关系了；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">将</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">中脱离；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">异常处理返回；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * CPU</span><span style="font-size: 10.5pt; font-family: 宋体;">重新执行刚刚发生异常的指令</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">mov(eax, vaddr)</span><span style="font-size: 10.5pt; font-family: 宋体;">；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * CPU</span><span style="font-size: 10.5pt; font-family: 宋体;">获得</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">这个虚地址，根据</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">CR3</span><span style="font-size: 10.5pt; font-family: 宋体;">寄存器指向的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">current-&gt;pgd</span><span style="font-size: 10.5pt; font-family: 宋体;">，利用建立好的页目录页表数据库，找到其对应的物理内存地址；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">将</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">eax</span><span style="font-size: 10.5pt; font-family: 宋体;">的内容写入</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的物理内存地址内；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">&nbsp;&nbsp;<br /> <br /> 7. </span><span style="font-size: 10.5pt; font-family: 宋体;">用户进程释放内存</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">，</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free(vaddr)</span><span style="font-size: 10.5pt; font-family: 宋体;">：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">找到该</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr</span><span style="font-size: 10.5pt; font-family: 宋体;">所在的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vm_area_struct</span><span style="font-size: 10.5pt; font-family: 宋体;">；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">找到</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vm_area_struct:start--end</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的所有页目录页表项，清空对应的所有页表项；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">释放这些页表项指向物理页面所对应的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">，并将这些</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">加入到</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">队列中；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">有必要还会清空一些页目录表项，并释放这些页目录表项指向的页表；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">task-&gt;mm-&gt;mmap</span><span style="font-size: 10.5pt; font-family: 宋体;">链中删除该</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vm_area_struct</span><span style="font-size: 10.5pt; font-family: 宋体;">并释放掉；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> </span><span style="font-size: 10.5pt; font-family: 宋体;">综合说明：</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> <br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">可用物理内存就是</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">中各</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">对应的物理内存；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">页目录页表数据库的主要目的是为</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">CPU</span><span style="font-size: 10.5pt; font-family: 宋体;">访问物理内存时转换</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">vaddr--&gt;paddr</span><span style="font-size: 10.5pt; font-family: 宋体;">使用，分配以及释放内存时不会用到，但是需要内核内存管理系统在合适时机为</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">CPU</span><span style="font-size: 10.5pt; font-family: 宋体;">建立好该库；</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"><br /> &nbsp; &nbsp; * </span><span style="font-size: 10.5pt; font-family: 宋体;">对于用户进程在</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">6</span><span style="font-size: 10.5pt; font-family: 宋体;">中获得的物理页面，有两个页表项对应，一个就是内核页目录页表数据库的某个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">pte[i ]</span><span style="font-size: 10.5pt; font-family: 宋体;">，一个就是当前进程内核页目录页表数据库的某个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"> pte[j]</span><span style="font-size: 10.5pt; font-family: 宋体;">，但是只有一个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">和其对应。如果此时调度到其他进程，其他进程申请并访问某个内存，则不会涉及到该物理页面，因为其分配时首先要从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;"> free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">中找一个</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">，而该物理页面对应的</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">page</span><span style="font-size: 10.5pt; font-family: 宋体;">已经从</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">free_list</span><span style="font-size: 10.5pt; font-family: 宋体;">中脱离出来了，因此不存在该物理页面被其他进程改写操作的情况。内核中通过</span><span style="font-size: 10.5pt; font-family: Verdana, sans-serif;">get_free_pages</span><span style="font-size: 10.5pt; font-family: 宋体;">等方式获取内存时，也不会涉及到该物理页面，原理同前所述。</span><img src ="http://www.cppblog.com/xieshuo/aggbug/204679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xieshuo/" target="_blank"> Torres</a> 2013-12-09 17:42 <a href="http://www.cppblog.com/xieshuo/archive/2013/12/09/204679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高性能JNI</title><link>http://www.cppblog.com/xieshuo/archive/2013/12/09/204678.html</link><dc:creator> Torres</dc:creator><author> Torres</author><pubDate>Mon, 09 Dec 2013 09:40:00 GMT</pubDate><guid>http://www.cppblog.com/xieshuo/archive/2013/12/09/204678.html</guid><wfw:comment>http://www.cppblog.com/xieshuo/comments/204678.html</wfw:comment><comments>http://www.cppblog.com/xieshuo/archive/2013/12/09/204678.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xieshuo/comments/commentRss/204678.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xieshuo/services/trackbacks/204678.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">from:&nbsp;</span><a href="http://www.cnblogs.com/whjiang/articles/1387364.html">http://www.cnblogs.com/whjiang/articles/1387364.html</a><br /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><br />1. 尽可能不要创建global reference和global weak reference. 创建这两类引用的JNI接口NewGlobalReference和NewGlobalWeakReference内部实现</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">有一个锁。这个锁使得在多处理器上的可扩展性非常差，因为各个线程都在等待这个锁。所以尽量不要在native保存java 对象的引用，情愿在每次</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">JNI call时都带点参数。当然，在native保持java对象的local reference是非常危险的，绝对不能那样干。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">2. 尽量不要使用GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical来pin住Java内存。JVM本身没有提供任何只pin住一块Java内存而不影</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">响GC的操作，所以这个操作是会阻止GC进行的。作为补偿，ReleasePrimitiveArrayCritical会产生一次隐式的GC调用。这样就可能出现在需要GC的时</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">候无法GC，而在不需要GC时进行无意义GC的情况。另外，这两个操作的实现中在某些情况下也可能触发锁。解决方法：如果是小块内存的话，情愿使</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">用Get&lt;Type&gt;ArrayRegion和Set&lt;Type&gt;ArrayRegion来在native和Java之间复制内存。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">3. 在Java appliation中尽量不要创建phantom reference或者soft reference。这些reference会极大的影响GC。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">我们先来谈谈JVM的GC。GC分为minor GC和full GC。Java内存分为young和old两代。在young memory中，每个线程都有自己的内存分配块（不和其它</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">线程共享），而old memory是由所有线程共享的。minor GC只对young memory作GC，而full GC对所有内存都做GC。minor GC是可以多线程并行进行的</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">，而full GC默认只能单线程执行。所以，一次full GC需要的时间可以是minor GC是10倍以上（可以用-verbose:gc观察）。所以在一般应用中，</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">minor GC的次数应该是full GC的10倍左右是比较理想的。minor GC会将无法收集的对象移动到old memory中去。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">minor GC不会对phantom reference和soft reference进行收集，只有full GC才会。这样的问题就是大量的这类对象积聚起来，产生许多的内存复制。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">这样每次minor GC可能就基本上没有释放多少内存，使得full GC就会被频繁触发。可能出现minor GC和full GC次数1：1的情况，甚至全是full GC。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">这样，无论是性能还是可扩展性都是非常差的。<br /></p><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">weak reference的影响好像小一些，但也应该尽量避免。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">在JNI开发中，使用这3种reference的主要目的是保证native资源的释放。因为java对象的finalize方法是不保证被调用的，所以必须用这些</p><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">reference来帮助实现native资源释放。为了避免上述的问题，一种可行的方法是将native资源serialize成一块内存，然后放到java对象中保存，从</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">而避免使用这些reference。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">4. NIO是不错的Java和native之间share memory的方法。但要注意它的性能。首先一定要设置对big endian还是little endian，防止JVM做额外的</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">endian转换动作。其次是在启动JVM时一定要加上-server选项，否则nio性能会非常差。在-server mode下，nio性能大概比java数组慢30%~50%.在-</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">client mode下，性能差1倍以上。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">5. 尽量不要在JNI去new Java String对象。这个比在java层new慢很多。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">6. 对java大对象（比方说数组），一定要仔细的tune他的大小。一般来说，小对象对GC比较友好。因为对象分配时先看每个线程自己的young memory</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">，如果找的到足够大的内存的话，就分配。否则在old memory中分配。因为old memory是shared，所以可能有锁开销。而且old memory中的对象只有</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">full GC才能释放它。所以对象比较小是比较好的。JVM的内存分配算法是为小对象优化过的，大量小对象的分配是很高效的，所以不用怕把大对象拆小。</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">在某些情况下，如果知道对象会活的很久的话，就让它大一点，增加它直接分配在old memory中的概率。这样可以节约young GC拷贝这个对象到old&nbsp;</span><br style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;" /><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">memory中的开销。</p><div></div><img src ="http://www.cppblog.com/xieshuo/aggbug/204678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xieshuo/" target="_blank"> Torres</a> 2013-12-09 17:40 <a href="http://www.cppblog.com/xieshuo/archive/2013/12/09/204678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ACM OJ Collection </title><link>http://www.cppblog.com/xieshuo/archive/2008/09/09/61412.html</link><dc:creator> Torres</dc:creator><author> Torres</author><pubDate>Tue, 09 Sep 2008 13:20:00 GMT</pubDate><guid>http://www.cppblog.com/xieshuo/archive/2008/09/09/61412.html</guid><wfw:comment>http://www.cppblog.com/xieshuo/comments/61412.html</wfw:comment><comments>http://www.cppblog.com/xieshuo/archive/2008/09/09/61412.html#Feedback</comments><slash:comments>32</slash:comments><wfw:commentRss>http://www.cppblog.com/xieshuo/comments/commentRss/61412.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xieshuo/services/trackbacks/61412.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这是在一个百度贴吧里转载的OJ及有用的网址收集！&nbsp;&nbsp;<a href='http://www.cppblog.com/xieshuo/archive/2008/09/09/61412.html'>阅读全文</a><img src ="http://www.cppblog.com/xieshuo/aggbug/61412.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xieshuo/" target="_blank"> Torres</a> 2008-09-09 21:20 <a href="http://www.cppblog.com/xieshuo/archive/2008/09/09/61412.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>