java-JVM
JVM ---------- java virtual machine. java runtime data area . 1.method area 方法区 共享 2.java stack 栈区, 线程 非共享 压入stack frame(method frame) 3.native method stack 本地方法栈 非共享 4.heap 堆 共享 a)堆内内存 1)old 2)young 2.1)eden 2.2)survivor 2.2.1)from(s1) 2.2.2)to(s2) 内存碎片整理. b)非堆内存 Metaspace code cache compressed class space c)离堆内存 OS - JVM [调参] -Xss -Xms -Xmx -Xmn //年轻代 -XX:NewSize -XX:MaxNewSize // -XX:NewRatio -XX:SurvivorRatio //eden区是单个幸存区的倍数 -XX:MetaspaceSize //元空间 -XX:MaxMetaspaceSize // -XX:PermSize -XX:MaxPermSize 5.program counter register 程序计数器 非共享 [GC] 垃圾回收,尽量回收。 没有任何一个指针能够直接或间接到达对象。 //显式回收 bytes = null ; System.gc() [工具软件] jvisualvm -> visual gc jconsole -> jmap -> 命令行 jmap -heap xxx Class.forName("加载类") ; ClassLoader ---------------- 类加载主要工作是类路径映射和文件定位。 com.it18zhang.java.io.MyInpuStream -> com/it18zhang/java/io/MyInpuStream.class ClassLoader 类使用委托模型来搜索类和资源。 每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图 亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。 虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器, 但是可以将它用作 ClassLoader 实例的父类加载器。 //类初始化过程 静态代码块在类加载期间调用,只调用一次。 Class.forName(...,false, ) @Test public void test1() throws Exception { System.out.println("hello world"); ClassLoader loader = ClassLoader.getSystemClassLoader() ; Class clazz = Class.forName("com.it18zhang.domain.Person",false,loader); System.out.println("hello world"); System.out.println("hello world"); System.out.println("hello world"); System.out.println("hello world"); Person p = null ; System.out.println(); Class clz = Person.class ; System.out.println(); p = new Person(); System.out.println(); System.out.println(); System.out.println(); } 自定义类加载器 ----------------- package com.it18zhang.classloader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; /** * 在定义类加载器 */ public class MyClassLoader extends ClassLoader { protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] data = loadClassBytes(name) ; return defineClass(data,0,data.length) ; } /** * 加载类的字节码文件 */ private byte[] loadClassByrtes(String name){ try{ File file = new File("d:/java" , name + ".class") ; FileInputStream fis = new FileInputStream(file) ; ByteArrayOutputStream baos = new ByteArrayOutputStream() ; int len = 0 ; byte[] buf = new byte[1024] ; while((len = fis.read(buf)) != -1){ baos.write(buf , 0 ,len); } fis.close(); baos.close(); return baos.toByteArray() ; } catch (Exception e){ e.printStackTrace(); } return null ; } } /** * 自定义类加载器 */ @Test public void test3() throws Exception { MyClassLoader loader = new MyClassLoader() ; Class clazz = loader.loadClass("HelloWorld") ; Object obj = clazz.newInstance(); Method m = clazz.getDeclaredMethod("sayHello") ; m.invoke(obj) ; System.out.println("over"); } NIO -------------- new io, 新型IO. jdk1.4 tcp //transfer control protocal udp //用户数据报协议 ServerSocket //服务器套接字 Socket //套接字 分线程 : 同步的,阻塞的。 ss.accept() socket.read() ; OutputStream //写 InputStream //读 非阻塞 , netty [术语] 1.Buffer, 缓冲区 capacity : 容量,长度 limit : 限制,能够使用的元素个数。 position :位置,指针的索引位置。 mark :记号 reset , 0 <= mark <= position <= limit <= capacity 1.flip() 拍板。 2.Channel 打开的连接,连接到实体(硬件,File,Socket) package com.it18zhang.java.test; import org.junit.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /** * */ public class TestNIO { @Test public void test1() throws Exception { for(int i = 1024 ; i <= 1024 * 1024 * 2; i = i * 2){ copyFile("d:/Koala.gif" , "e:/1.gif", i) ; } } /** * 拷贝文件,指定不同缓冲区大小 */ public static void copyFile(String srcFile ,String destFile , int bufSize) throws Exception { File targFile = new File(destFile) ; if(targFile.exists()){ targFile.delete() ; } // FileInputStream fis = new FileInputStream(srcFile) ; //得到源文件通道 FileChannel srcFC = fis.getChannel(); // FileOutputStream fos = new FileOutputStream(destFile) ; FileChannel outFC = fos.getChannel() ; //缓冲区 long start = System.nanoTime() ; ByteBuffer buf = ByteBuffer.allocateDirect(bufSize) ; while(srcFC.read(buf) != -1){ buf.flip() ; outFC.write(buf) ; buf.clear(); } System.out.println(bufSize + "\t : " + (System.nanoTime() - start)); srcFC.close(); fis.close(); outFC.close(); fos.close(); } /** * 分配内存 */ @Test public void test2(){ int len = 1024 * 1024 * 500 ; //堆内内存 ByteBuffer.allocate(len) ; //离堆内存 ByteBuffer.allocateDirect(len) ; System.out.println(); } } // ByteBuffer.allocate() ==> HeapByteBuffer //离堆 ByteBuffer.allocateDirect() ==> DirectByteBuffer System.gc() ; NIO操纵离堆内存,手动回收离队内存,使用反射手段。 ----------------------------------------------- @Test public void test2() throws Exception { int len = 1024 * 1024 * 500 ; // //堆内内存 // ByteBuffer buf = ByteBuffer.allocate(len) ; // System.gc(); // buf = null ; // System.gc(); // buf.clear() ; // System.gc(); //离堆内存 ByteBuffer buf = ByteBuffer.allocateDirect(len) ; Method m = buf.getClass().getDeclaredMethod("cleaner") ; m.setAccessible(true); Cleaner cleaner = (Cleaner) m.invoke(buf); cleaner.clean(); buf.put((byte)100) ; buf.get(); System.gc(); System.out.println(); System.out.println(); System.out.println(); } @Test public void test3() throws Exception { RandomAccessFile raf = new RandomAccessFile("d:/java/1.txt" ,"rw") ; FileChannel fc = raf.getChannel(); MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_WRITE , 2,5) ; buf.put((byte)97) ; buf.put((byte)98) ; buf.put((byte)99) ; buf.flip(); buf.put((byte) 100) ; buf.put((byte) 100) ; buf.put((byte) 100) ; fc.close(); } 机械硬盘 ------------------ 100m/s. 零拷贝 ------------------ 常规 64k 600m 475,276,088 零拷贝 64k 600m 349,630,104 /** * 测试正常拷贝 */ @Test public void testNormalCopy() throws Exception { FileInputStream fis = new FileInputStream("D:\\downloads\\iso\\CentOS-7-x86_64-Minimal-1511.iso") ; long start = System.nanoTime() ; FileOutputStream fos = new FileOutputStream("e:/1.iso") ; byte[] bytes = new byte[64 * 1024] ; int len = -1 ; while((len = fis.read(bytes)) != -1){ fos.write(bytes,0,len); } fos.close(); fis.close(); System.out.println(System.nanoTime() - start); } /** * * @throws Exception */ @Test public void testZeroCopy() throws Exception { long start = System.nanoTime() ; File f = new File("D:\\downloads\\iso\\CentOS-7-x86_64-Minimal-1511.iso") ; FileInputStream fis = new FileInputStream(f) ; FileOutputStream fos = new FileOutputStream("f:/1.iso") ; fis.getChannel().transferTo(0, f.length(), fos.getChannel()) ; fos.close(); fis.close(); System.out.println(System.nanoTime() - start); } 网络适配器工作模式 -------------------- 单工 //只能向一个方向传输数据。 双工 //可以双向传输数据 半双工 //同一时刻只能向一方传输。 全双工 //同一时刻只能向一方传输。 NIO Socket -------------- 1.ServerSocketChannel 服务器通道, ServerSocket 配置阻塞模式. ServerSocketChannel.open() 2.SockdetChannel connect(); 3.Selector 挑选器, 通道需要在该组件中注册,注册后会产生key(SelectionKey),该key关联到channel 注册生成的key存放在keys集合中。 内部维护三个集和 1.keys 存放所有注册的key 2.selectedkeys 存放挑选出来的key,通道上发生了自己感兴趣的事件。 处理完该集合后,需要对该集合进行清空处理。 3.cancelledkeys 存放即将被撤销的通道的key。 4.SelectionKey 注册产生的key对象,内部封装channel引用,该兴趣的事件。 5.channel同buffer协同 channel.read()|write() 6.NIO核心是非阻塞 不需要创建大量线程,避免cpu在大量线程上下文之间进行切换,cpu运行效率很高。