- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- 詳細總結Java堆棧內存、堆外內存、零拷貝淺析與
堆棧內存,顧名思義,指的是堆內存以及棧內存,其中,堆內存是由Java GC進(jìn)行管理的內存區域,而棧內存則是線(xiàn)程內存。關(guān)于棧內存,這里不去細說(shuō)。以Hotspot為例,堆內存的簡(jiǎn)要結構如下圖所示:
而堆棧的關(guān)系,我們可以通過(guò)一行簡(jiǎn)單的代碼來(lái)理解:
public static void main(String[] args) { Object o = new Object(); }
上述代碼主要完成了兩件事,new Object( ) 在堆上開(kāi)辟了一塊內存,也就是說(shuō),new Object( )是分配在堆上的;而變量o,則是在線(xiàn)程main的棧上面的,它指向了new Object( ) 開(kāi)辟的堆內存地址。簡(jiǎn)單來(lái)說(shuō),程序中創(chuàng )建的對象,都存儲在堆內存中,棧內存包含對它的引用。
簡(jiǎn)單來(lái)說(shuō),除了堆棧內存,剩下的就都是堆外內存了(當然,這是從Java運行時(shí)內存的角度來(lái)看),堆外內存直接受操作系統管理,而不是虛擬機。而使用堆外內存的原因,主要有幾點(diǎn):
總結上述內容中對堆棧內存與堆外內存的說(shuō)明,主要解決了兩個(gè)疑問(wèn):“零拷貝”是從哪拷貝到哪?“零拷貝”是怎么優(yōu)化掉這一拷貝操作的?
在Java中,提供了一些使用堆外內存以及DMA的方法,能夠在很大程度上優(yōu)化用戶(hù)進(jìn)程的IO效率。這里,給出一份拷貝文件的代碼,分別使用BIO、NIO和使用堆外內存的NIO進(jìn)行文件復制,簡(jiǎn)單對比其耗時(shí)。
這里我使用一個(gè)200MB左右的pdf文件進(jìn)行拷貝操作,你可以另外指定更大的文件,文件越大對比越明顯。這里我運行出來(lái)的延時(shí),BIO的平均耗時(shí)1500ms上下,NIO耗時(shí)120ms左右, 使用堆外內存的NIO耗時(shí)100ms上下。
package top.jiangnanmax.nio; import java.io.*; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; /** * @author jiangnanmax * @email jiangnanmax@gmail.com * @description CopyCompare * @date 2021/5/7 **/ public class CopyCompare { public static void main(String[] args) throws Exception { String inputFile = "/tmp/nio/input/HyperLedger.pdf"; String outputFile = "/tmp/nio/output/HyperLedger.pdf"; long start = System.currentTimeMillis(); nioCopyByDirectMem(inputFile, outputFile); long end = System.currentTimeMillis(); System.out.println("cost time: " + (end - start) + " ms"); deleteFile(outputFile); } /** * 使用傳統IO進(jìn)行文件復制 * * 平均耗時(shí) 15** ms * * @param sourcePath * @param destPath */ private static void bioCopy(String sourcePath, String destPath) throws Exception { File sourceFile = new File(sourcePath); File destFile = new File(destPath); if (!destFile.exists()) { destFile.createNewFile(); } FileInputStream inputStream = new FileInputStream(sourceFile); FileOutputStream outputStream = new FileOutputStream(destFile); byte[] buffer = new byte[512]; int lenRead; while ((lenRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, lenRead); } inputStream.close(); outputStream.close(); } /** * 使用NIO進(jìn)行文件復制,但不使用堆外內存 * * 平均耗時(shí) 1** ms, 比BIO直接快了一個(gè)數量級??? * * @param sourcePath * @param destPath */ private static void nioCopy(String sourcePath, String destPath) throws Exception { File sourceFile = new File(sourcePath); File destFile = new File(destPath); if (!destFile.exists()) { destFile.createNewFile(); } FileInputStream inputStream = new FileInputStream(sourceFile); FileOutputStream outputStream = new FileOutputStream(destFile); FileChannel inputChannel = inputStream.getChannel(); FileChannel outputChannel = outputStream.getChannel(); // transferFrom底層調用的應該是sendfile // 直接在兩個(gè)文件描述符之間進(jìn)行了數據傳輸 // DMA outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); inputChannel.close(); outputChannel.close(); inputStream.close(); outputStream.close(); } /** * 使用NIO進(jìn)行文件復制,并使用堆外內存 * * 平均耗時(shí)100ms上下,比沒(méi)使用堆外內存的NIO快一點(diǎn) * * @param sourcePath * @param destPath */ private static void nioCopyByDirectMem(String sourcePath, String destPath) throws Exception { File sourceFile = new File(sourcePath); File destFile = new File(destPath); if (!destFile.exists()) { destFile.createNewFile(); } FileInputStream inputStream = new FileInputStream(sourceFile); FileOutputStream outputStream = new FileOutputStream(destFile); FileChannel inputChannel = inputStream.getChannel(); FileChannel outputChannel = outputStream.getChannel(); MappedByteBuffer buffer = inputChannel.map(FileChannel.MapMode.READ_ONLY, 0, inputChannel.size()); outputChannel.write(buffer); inputChannel.close(); outputChannel.close(); inputStream.close(); outputStream.close(); } /** * 刪除目標文件 * * @param target */ private static void deleteFile(String target) { File file = new File(target); file.delete(); } }
到此這篇關(guān)于詳細總結Java堆棧內存、堆外內存、零拷貝淺析與代碼實(shí)現的文章就介紹到這了,更多相關(guān)Java堆棧內存 堆外內存 零拷貝淺析內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站