面试官:做个上传文件吧?
你:嗯
面试官:那就说说BIO NIO AIO的概念吧。
你:BIO 同步阻塞 File,输入输出流,HttpUrlConnection
NIO 同步非阻塞 Channel Selector Buffer等新抽象,多路服务,提供更接近系统底层的数据操作。
AIO/NIO2 异步非阻塞 基于事件和回调机制,任务完成时,系统回去通知相应的线程
面试官:说说InputStream和OutputStream,Reader/Wrtier的区别
你:前处理字节流,后处理字符
面试官:java文件copy有哪些实现方式?
你:1. java.io的FileInputStream FileOutputStream
2. java.nio的transferTo transferFrom
3. Files.copy
面试官:那他们的实现原理是什么?
你:java.io的FileInputStream FileOutputStream是用户态到内核态的互相切换,java.nio的transferTo transferFrom是在内核态直接进行的, Files.copy基本调用的系统的本地方法在用户态copy。所以一般还是NIO得快点,因为少了一些用户态到内核态的切换。
面试官:那如果文件很大,内存不会被爆了吗?
你:会,但是我们可以使用BufferedInputStream BufferedOutputStream来解决。
面试官: 说说ByteBuffer的工作过程。
你:新建一个BeyteBuffer,设置capacity,capacity就是它的上限。写入字节的时候,position就会增长,如果要读出已经写入的数据,就调用flip方法,position重置为0。如果要从头开始读,就调用rewind方法,并重置position为0。
面试官:ByteBuffer和MappedByteBuffer有啥区别?
你:名字不一样,Mapped就是直接映射到内存,省去了用户态到内核态的切换。
面试官:Buffer如何区分是堆内还是堆外的?
你:isDirect
面试官:Direct的Buffer有什么好处和坏处?
你:直接写堆外的内存上,内存地址不变,内核可以安全的访问,效率高,不要再堆内维护,省掉了GC的消耗。但是这不是说GC不管它了,只要在FULL GC的时候才回去收集堆外的Buffer。可能会造成OOM的问题,所以一般适合长期使用的Buffer。要尽量在程序里进行垃圾收集,system.gc。
面试官:那有什么方法看堆外的buffer吗?
你:使用NMT -XX:NativeMemoryTracking={summary|detail},不过这玩意儿很耗性能,一般在5%到10%,而且你不太可能说重启服务在命令里加上这个flag,还是用APM来监控来的稳妥,还可以查看过去的状态图。