java-JVM

Posted 飞机耳朵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 + "	 : " + (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运行效率很高。

 

以上是关于java-JVM的主要内容,如果未能解决你的问题,请参考以下文章

java-JVM-堆内存

java-JVM-1

Java-JVM OutOfMemory 情况(JDK8)

JAVA-JVM 运行时内存结构(Run-Time Data Areas)

微信小程序代码片段

VSCode自定义代码片段——CSS选择器