当前位置: 首页 > news >正文

做网站用java还是php网店运营实训报告

做网站用java还是php,网店运营实训报告,中国建筑企业500强排名,企业为什么要做短视频营销DirectByteBuffer和HeapByteBuffer是Java NIO中ByteBuffer的两种实现方式。 HeapByteBuffer是在Java堆上分配的字节缓冲区,它使用数组来存储数据。HeapByteBuffer的优点是它具有良好的兼容性和可移植性,且在大多数情况下性能表现良好。它适用于大部分的…

DirectByteBuffer和HeapByteBuffer是Java NIO中ByteBuffer的两种实现方式。

HeapByteBuffer是在Java堆上分配的字节缓冲区,它使用数组来存储数据。HeapByteBuffer的优点是它具有良好的兼容性和可移植性,且在大多数情况下性能表现良好。它适用于大部分的应用场景,并且在内存管理方面具有更好的可控性和可调优性。

DirectByteBuffer是在直接内存中分配的字节缓冲区,它不是使用Java堆上的数组来存储数据,而是使用JNI(Java Native Interface)来直接操作本地内存。DirectByteBuffer的优点是它可以提供更高的IO性能,因为数据可以直接从内核缓冲区复制到DirectByteBuffer中,避免了数据的复制。它适用于处理大量的数据、网络数据传输、以及需要与本地库进行高效交互的场景。

堆内内存与堆外内存

堆内内存(Heap Memory)和堆外内存(Off-Heap Memory)是指在JAVA中两种不同的内存分配方式,其中的堆指的是JVM中的堆。

堆内内存:

  • 堆内内存是指在Java堆中分配的内存。在Java中,对象的创建和销毁都是在堆内存中进行的。堆内内存由Java虚拟机(JVM)的垃圾回收机制进行管理,即通过垃圾回收器自动进行内存回收。

  • 堆内内存具有自动内存管理的特性,程序员不需要手动释放内存。Java的堆内内存使用的是Java堆中的对象引用,通过引用计数和可达性分析等机制进行垃圾回收。

堆外内存:

  • 堆外内存是指在Java堆之外分配的内存,也称为直接内存(Direct Memory)。

  • 堆外内存通常由本地操作系统管理,不受JVM垃圾回收的控制。程序员需要手动释放这部分内存,一般通过Java NIO中的ByteBuffer的cleaner()方法或显式调用free()方法来释放。

  • 堆外内存的分配和释放并不会受到Java堆内存的限制,可以提供更大的内存空间。

  • 堆外内存适用于需要更高的IO性能、处理大量数据或需要与本地库进行高效交互的场景。在网络编程、数据库操作、图形处理等领域常常使用堆外内存。

需要注意的是,堆外内存的分配和释放需要谨慎操作,因为它不受Java堆内存的自动管理,容易导致内存泄漏和内存溢出等问题。因此,在使用堆外内存时,需要合理地管理内存的生命周期。

HeapByteBuffer

HeapByteBuffer主要用于在JVM堆内存中分配和操作字节。

HeapByteBuffer的使用如下:

package com.morris.io;import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;/*** HeapByteBuffer的使用*/
public class HeapByteBufferDemo {public static void main(String[] args) throws IOException {ByteBuffer byteBuffer = ByteBuffer.allocate(1024);byteBuffer.put("hello".getBytes(StandardCharsets.UTF_8));byteBuffer.flip();FileOutputStream fos = new FileOutputStream("HeapByteBufferDemo.txt");FileChannel channel = fos.getChannel();channel.write(byteBuffer);channel.close();fos.close();}
}

产生的系统调用如下:

openat(AT_FDCWD, "HeapByteBufferDemo.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
fstat(4, {st_mode=S_IFREG|0777, st_size=0, ...}) = 0
write(4, "hello", 5)                    = 5
close(4)

HeapByteBuffer的内部实现通过使用数组来存储数据,可以在HeapByteBuffer的构造方法中看到数组的创建:

HeapByteBuffer(int cap, int lim) {            // package-private// 创建了一个字节数组super(-1, 0, lim, cap, new byte[cap], 0);
}

DirectByteBuffer

DirectByteBuffer主要用于在操作系统的内存中分配和操作字节。与HeapByteBuffer不同,DirectByteBuffer直接在操作系统的内存中分配数据。

DirectByteBuffer的使用如下:

package com.morris.io;import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;/*** DirectByteBuffer的使用*/
public class DirectByteBufferDemo {public static void main(String[] args) throws IOException {System.in.read();ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024*128);byteBuffer.put("hello".getBytes(StandardCharsets.UTF_8));byteBuffer.flip();System.in.read();FileOutputStream fos = new FileOutputStream("DirectByteBufferDemo.txt");FileChannel channel = fos.getChannel();channel.write(byteBuffer);channel.close();fos.close();}
}

产生的系统调用如下:

mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fdb8c000000
openat(AT_FDCWD, "DirectByteBufferDemo.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
fstat(4, {st_mode=S_IFREG|0777, st_size=0, ...}) = 0
write(4, "hello", 5)                    = 5
close(4)

我们在应用程序中申请了128KB(128*1024=131072B)的内存,底层会使用mmap系统调用在进程的堆内分配一块132KB的内存,这块内存是在进程的堆内,JVM的堆外

在上面的例子中,我们申请了128KB的内存,实际上分配一块132KB的内存,为什么会多分配4KB呢?我也没明白?

DirectByteBuffer的构造方法如下:

DirectByteBuffer(int cap) {                   // package-privatesuper(-1, 0, cap, cap);boolean pa = VM.isDirectMemoryPageAligned();int ps = Bits.pageSize();long size = Math.max(1L, (long)cap + (pa ? ps : 0));Bits.reserveMemory(size, cap);long base = 0;try {base = unsafe.allocateMemory(size);} catch (OutOfMemoryError x) {Bits.unreserveMemory(size, cap);throw x;}unsafe.setMemory(base, size, (byte) 0);if (pa && (base % ps != 0)) {// Round up to page boundaryaddress = base + ps - (base & (ps - 1));} else {address = base;}cleaner = Cleaner.create(this, new Deallocator(base, size, cap));att = null;
}

我们可以看到DirectByteBuffer底层是使用unsafe.allocateMemory来申请堆外内存,这是一个本地方法。

实际上我们自己也可以借助unsafe来申请堆外内存:

package com.morris.io;import sun.misc.Unsafe;import java.io.IOException;
import java.lang.reflect.Field;/*** 使用unsafe来申请内存*/
public class UnsafeAllocateMemoryDemo {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException {Unsafe unsafe = getUnsafe();long address = unsafe.allocateMemory(128 * 1024);unsafe.freeMemory(address);}public static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {Field field = Unsafe.class.getDeclaredField("theUnsafe");field.setAccessible(true);return (Unsafe) field.get(null);}
}

产生的系统调用如下:

mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe07801c000
munmap(0x7fe07801c000, 135168)          = 0

当使用mmap系统调用申请到堆外内存空间后,可以使用munmap系统调用来释放这块内存。

为什么要使用DirectByteBuffer?

从上面的例子可以看到DirectByteBuffer在使用的过程中会比HeapByteBuffer多一次系统调用,性能不如HeapByteBuffer,为什么性能差却还使用DirectByteBuffer呢?

看源码,这里以FileChannel实现类FileChannelImpl.read中为例:

sun.nio.ch.FileChannelImpl#write(java.nio.ByteBuffer)

public int write(ByteBuffer var1) throws IOException {this.ensureOpen();if (!this.writable) {throw new NonWritableChannelException();} else {synchronized(this.positionLock) {int var3 = 0;int var4 = -1;byte var5;try {this.begin();var4 = this.threads.add();if (this.isOpen()) {do {var3 = IOUtil.write(this.fd, var1, -1L, this.nd);} while(var3 == -3 && this.isOpen());int var12 = IOStatus.normalize(var3);return var12;}var5 = 0;} finally {this.threads.remove(var4);this.end(var3 > 0);assert IOStatus.check(var3);}return var5;}}
}

然后会调用IOUtil.write():

static int write(FileDescriptor var0, ByteBuffer var1, long var2, NativeDispatcher var4) throws IOException {if (var1 instanceof DirectBuffer) {return writeFromNativeBuffer(var0, var1, var2, var4);} else {int var5 = var1.position();int var6 = var1.limit();assert var5 <= var6;int var7 = var5 <= var6 ? var6 - var5 : 0;ByteBuffer var8 = Util.getTemporaryDirectBuffer(var7);int var10;try {var8.put(var1);var8.flip();var1.position(var5);int var9 = writeFromNativeBuffer(var0, var8, var2, var4);if (var9 > 0) {var1.position(var5 + var9);}var10 = var9;} finally {Util.offerFirstTemporaryDirectBuffer(var8);}return var10;}
}

当向FileChannel中写数据,数据来源是DirectByteBuffer时,可以直接将DirectByteBuffer中的数据写入到文件中。

当向FileChannel中写数据,数据来源是HeapByteBuffer时,需要先将数据从HeapByteBuffer写入到一个临时的DirectByteBuffer中,再将临时DirectByteBuffer中的数据写入到文件中。

所以,当java程序数据需要频繁与本地io(本地磁盘、socket传输数据时),使用HeapByteBuffer读取时要多复制一次数据(即从DirectByteBuffer再复制到heapByteBuffer)。再加上写数据到本地时,又要再从HeapByteBuffer复制到另一个DirectByteBuffer,多了两次复制。

HeapByteBuffer底层其实是java的字节数组,而java字节数组是一个java对象,对象的内存是由jvm的堆进行管理的,那么不可避免的是GC时年轻代的eden、suvivor到老年代的各种复制以及回收。当字节数组比较小的时候还好说,如果是大对象,那么对于jvm的GC来说是一个很大的负担。而使用DirectByteBuffer,则是把字节数组交给操作系统管理(堆外内存),就可以极大的减少jvm的负担了。

DirectByteBuffer和HeapByteBuffer的使用场景

什么情况下使用DirectByteBuffer?

  • 频繁的native IO,即java程序与本地磁盘、socket传输数据。

  • 不需要经常创建和销毁DirectByteBuffer对象,有系统调用代价大,可以使用池复用DirectByteBuffer

  • DirectByteBuffer不会占用堆内存。也就是不会受到堆大小限制,只在DirectByteBuffer对象被回收后才会释放该缓冲区。

  • 大文件造成大对象,对GC负担比较重的情况

什么情况下使用HeapByteBuffer?其实除了上述的DirectByteBuffer使用场景之外的,基本可以用HeapByteBuffer。

  • 数据仅在java程序中流转传输,不与本地进行IO,例如Netty的责任链中传递对象可以使用HeapByteBuffer

  • 容量低,对GC负担低。快速回收

http://www.zhongyajixie.com/news/15732.html

相关文章:

  • 室内设计和平面设计区别山西免费网站关键词优化排名
  • 什么网站可以做设计赚钱吗企业培训师
  • 云南工贸网站建设百度霸屏推广多少钱一个月
  • 网站建设方案-奢侈品灰色词快速排名方法
  • 犀牛云做网站一年多少钱谷歌浏览器官方正版下载
  • 鄱阳网站建设网络运营课程培训班
  • 怎么做系部网站首页百度seo最新算法
  • 自己做的网站怎么维护网站怎么提升关键词排名
  • 宁乡电商网站建设价格百度快速排名优化技术
  • 动态网站开发与实例网站软文是什么
  • 长春网站关键词推广百度在线扫一扫
  • 甘肃网站建站系统平台在线咨询
  • 无锡网站制作难吗网络推广和竞价怎么做
  • 什么是灰色网站bt磁力搜索器
  • 一家专门做打折的网站网站宣传推广文案
  • 经过开发建设 网站上线了整站优化要多少钱
  • wordpress接入翼支付广州seo服务
  • 武汉建立网站的公司网站怎么推广效果好一点呢
  • 成都模板建站优化大师软件下载
  • 学习做网站难吗seo培训机构排名
  • 连云港做鸭网站大数据分析网站
  • 建设银行投资网站首页做推广app赚钱的项目
  • 中英双语网站程序郑州计算机培训机构哪个最好
  • 石家庄网站做网站seo兼职工资一般多少
  • 做网站的名字大全下载百度网盘app最新版
  • 兰州碧桂园推广优化关键词
  • 网站开发 外包建站网站关键词优化
  • 政务网站建设的重要性店铺如何运营和推广
  • 这个网站做海外推广网站关键词查询网址
  • 沈阳网站设计公司有哪些网站优化方案范文