JVM

文章目录

Java脑图

谈谈对Java的理解

语言特性 泛型、反射、Lamda表达式 面向对象 封装、继承、多态 类库 集合、并发库、io、网络、NIO 异常处理

平台无关性

特点

编译 生成.class 二进制文件 javac xxx.java 运行 java xxx 命令反编译帮助 javap -help 反汇编 javap -c xxx

类测试complie

/**
 * @Author bennyrhys
 * @Date 2020-03-23 23:38
 */
public class complie {
    public static void main(String[] args) {
        int i = 5, j = 6;
        i++;
        ++j;
        System.out.println(i);
        System.out.println(j);
    }
}

编译运行

(base) bennyrhysdeMacBook-Pro:src bennyrhys$ javac complie.java 
(base) bennyrhysdeMacBook-Pro:src bennyrhys$ java complie
6
7

反编译

(base) bennyrhysdeMacBook-Pro:src bennyrhys$ javap -help
用法: javap <options> <classes>
其中, 可能的选项包括:
  -help  --help  -?        输出此用法消息
  -version                 版本信息
  -v  -verbose             输出附加信息
  -l                       输出行号和本地变量表
  -public                  仅显示公共类和成员
  -protected               显示受保护的/公共类和成员
  -package                 显示程序包/受保护的/公共类
                           和成员 (默认)
  -p  -private             显示所有类和成员
  -c                       对代码进行反汇编
  -s                       输出内部类型签名
  -sysinfo                 显示正在处理的类的
                           系统信息 (路径, 大小, 日期, MD5 散列)
  -constants               显示最终常量
  -classpath <path>        指定查找用户类文件的位置
  -cp <path>               指定查找用户类文件的位置
  -bootclasspath <path>    覆盖引导类文件的位置
(base) bennyrhysdeMacBook-Pro:src bennyrhys$ javap -c complie
Compiled from "complie.java"
public class complie {
  public complie();
  // 构造函数
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_5 // 常量1栈顶
       1: istore_1 // 将栈顶放到局部变量1
       2: bipush        6
       4: istore_2
       5: iinc          1, 1
       8: iinc          2, 1
      11: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      14: iload_1
      15: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      18: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      21: iload_2
      22: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
      25: return
}
(base) bennyrhysdeMacBook-Pro:src bennyrhys$ 

不同系统解析class文件成为不同机器码

链接远程 ssh root@39.106.75.223 上传本地文件

创建相同包目录 mkdir -p 目录 复制文件 cp 文件 指定目录

为什么不直接编译成机器码

准备工作:无需重复校验语法 可扩展:字节码可由不同语言生成

JVM如何加载.class文件

Native

native接口

谈谈反射

理解

代码效果

代码

Robot

package reflect;

/**
 * @Author bennyrhys
 * @Date 2020-03-24 16:31
 * 反射-机器人
 */
public class Robot {
    private String name;

    public void sayHi(String helloSentence) {
        System.out.println(helloSentence+name);
    }

    private String throwHello(String tag) {
        return "Hello" + tag;
    }
}

ReflectSample

package reflect;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author bennyrhys
 * @Date 2020-03-24 16:35
 * 反射就是把类中的各个成分,映射成Java对象,Class,Method,Field
 */
public class ReflectSample {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 获取类class,使用全路径,抛异常
        Class<?> rc = Class.forName("reflect.Robot");
        // 创建实例
        // 由于 public T newInstance() 返回值范型,需要强转,抛异常
        Robot o = (Robot) rc.newInstance();

        System.out.println("Class name is:"+rc.getName());

        // 私有的只有反射可以获取到
        // getDeclaredMethod 获取到所有的方法,但是不能获取继承的方法,接口实现的方法
        Method getHello = rc.getDeclaredMethod("throwHello", String.class);
        // 默认false私有的,设置可访问私有的,否则报错
        getHello.setAccessible(true);
        // 调用私有方法. 对象实例,传入参数
        Object str = getHello.invoke(o, "Bennyrhys");
        System.out.println("getHello Private resulet is:"+ str);

        // 调用共有方法,另一种方法【只能调用pubic方法,和继承方法,和实现方法】
        Method sayHi = rc.getMethod("sayHi", String.class);
        sayHi.invoke(o, "Welcome");

        // 获取私有属性
        Field name = rc.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o, "Bennyrhys");

        sayHi.invoke(o, "Welcome");
    }
}

谈谈ClassLoader

类从编译到执行的过程

谈谈ClassLoader

追一下源码

抽象类

最重要的方法:给定类名去加载一个类

parent成员变量

属于ClassLoader,由此可见有多种类

ClassLoader种类

BootStrap

JVM核心库,C++编写

Ext

继承制URL

通过路径获取文件 文件用到才加载

 // 获取ExtClassLoad加载路径
        System.out.println(System.getProperty("java.ext.dirs"));

Extensions

/Users/bennyrhys/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

App

  // 获取AppClassLoader的classPath
        System.out.println(System.getProperty("java.class.path"));

/Users/bennyrhys/Documents/Idea_Demo/test/out/production/test 会到此路径找我们的class进行加载

/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/charsets.jar:/L ibrary/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/lib/tools.jar:/Users/bennyrhys/Documents/Idea_Demo/test/out/production/test:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar

(base) bennyrhysdeMacBook-Pro:reflect bennyrhys$ pwd

/Users/bennyrhys/Documents/Idea_Demo/test/out/production/test/reflect

(base) bennyrhysdeMacBook-Pro:reflect bennyrhys$ ls

ReflectSample.class Robot.class

自定义

根据名称或者位置寻找文件 进行解析,文件数据格式,,返回class对象

找类

抛出类找不到异常

可以在此处定义如何找到类 重新定义类

代码实现效果

代码

ZhangSan.java

/**
 * @Author bennyrhys
 * @Date 2020-03-24 19:48
 */
public class ZhanSan {
    static {
        System.out.println("Hello ZhanSan");
    }
}

MyClassLoader

package reflect;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * 自定义类加载
 * @Author bennyrhys
 * @Date 2020-03-24 19:54
 */
public class MyClassLoader extends ClassLoader{
    private String path;
    private String classLoaderName;


    public MyClassLoader(String path, String classLoaderName) {
        this.path = path;
        this.classLoaderName = classLoaderName;
    }

    // 用于寻找类文件
    @Override
    public Class findClass(String name) throws ClassNotFoundException {
        byte[] b = loadclassName(name);
        return defineClass(name, b, 0, b.length);
    }

    // 用于加载类文件
    private byte[] loadclassName(String name) {
        name = path + name + ".class";
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i = in.read()) != -1) {
                out.write(i);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                out.close();
                in.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
}

MyClassLoaderChecker

package reflect;

/**
 * @Author bennyrhys
 * @Date 2020-03-24 20:14
 */
public class MyClassLoaderChecker {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader m = new MyClassLoader("/Users/bennyrhys/Desktop/jquery/", "myClassLoad");
        Class zhanSan = m.loadClass("ZhanSan");
        System.out.println(zhanSan.getClassLoader());
        zhanSan.newInstance();
    }
}

使用场景展望

自定义类加载 从网络中获取标准二进制流,进行类加载 可以对敏感的.class加密,在findClass里面解密 对生成的二进制流添加一些类信息 甚至思考一下AOP用这种方法实现

JAVA字节码增强技术之ASM ASM是一款基于java字节码层面的代码分析和修改工具;无需提供源代码即可对应用嵌入所需debug代码,用于应用API性能分析,代码优化和代码混淆等工作。ASM的目标是生成,转换和分析已编译的java class文件,可使用ASM工具读/写/转换JVM指令集。 ASM工具提供两种方式来产生和转换已编译的class文件,它们分别是基于事件和基于对象的表示模型。其中,基于事件的表示模型使用一个有序的事件序列表示一个class文件,class文件中的每一个元素使用一个事件来表示,比如class的头部,变量,方法声明JVM指令都有相对应的事件表示,ASM使用自带的事件解析器能将每一个class文件解析成一个事件序列。而基于对象的表示模型则使用对象树结构来解析每一个文件。

类加载器双亲委派机制

多种ClassLoader相互协作

跟源码

理解调用

loadClass

如何确定层级调用关系的?

按理来说parent都是URL,但为啥层级实际关系不是这样

但实际上是有层级的

// 查看parent的
        System.out.println(zhanSan.getClassLoader().getParent()); // app
        System.out.println(zhanSan.getClassLoader().getParent().getParent()); // ext
        System.out.println(zhanSan.getClassLoader().getParent().getParent().getParent()); // c++

reflect.MyClassLoader@1540e19d

sun.misc.LauncherAppClassLoader@18b4aac2sun.misc.LauncherExtClassLoader@14ae5a5

null

还是不信调用C++?

为啥要用双亲委派机制去加载类?

你了解Java的内存模型吗?

理解

进程受限

进程受限于操作系统提供的可寻址空间。 可寻址空间由操作系统的位数决定 32位 4G

地址空间划分

内核空间 操作系统程序,c运行,链接计算机硬件,提供联网,虚拟内存 可以访问所有内存 用户空间 java实际运行

32位 进程最大访问3G 64位 进程最大访问512G

内存模型

中间核心部分

Java运行在虚拟机,运行时,会划分不同数据区域,方便内存空间方便管理

C编译器在划分内存的时候 数据段: 堆、栈、静态数据区 代码段:

程序计数器

虚拟机栈

栈的内存不需要gc,移除栈帧自动释放

口语指令分析代码

口语化指令

递归为什么会引发异常1

异常2

当虚拟机栈可以动态扩展时,无法申请足够多的内存 容易导致系统假死

本地方法栈

元空间与永久代区别

jdk8以后把元数据数据放到本地堆内存叫元空间 该区域在jdk7及以前属于永久代 元空间和永久代都是用来存储Class信息 (包括class的Methed和Field等) 元空间和永久代均是方法区的实现,只是实现有所不同。 方法区是JVM的一种规范 jdk1.7之后位于方法区的字符串常量池,已被移动到了Java堆中 jdk1.8中元空间替代了永久代 解决了运行空间不足可能产生的异常

堆(Heap)

线程共享的堆 存储对象实例 可以处在物理上不连续的空间,逻辑连续即可,可扩展的

JVM存储角度

三大性能调优参数-Xms -Xmx -Xss含义

调整JVM,堆、线程,所占内存的大小

Java内存模型中堆和栈的区别

内存分配策略

堆和栈的区别

通过栈中的引用变量访问堆中的地址 栈存储堆中首地址(引用变量) 到其作用域之外后释放 堆,数组首地址、实例对象 占据的内存不会被释放。只有在没有引用变量之后才会被视为垃圾回收,不确定的时间被垃圾回收机制释放掉

元空间、堆、线程、独占部分间的联系-内存角度

不同jdk的intern()方法区别-jdk6 VS jkd6+

重现jdk6永久代内存异常

切换到1.7、1.8

对比不同jdk的intern()

1.7

1.6

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:https://blog.csdn.net/weixin_43469680复制
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • JVM之JVM初探

    JVM的类加载器为ClassLoader采用双亲委派模型机制进行加载类。 双亲委派模型机制: 根据父子关系一直往顶层找是否被其他父级parent类加载器加载...

    用户7528483
  • JVM: JVM 内存划分

    https://www.cnblogs.com/paulwang92115/p/12251476.html

    用户5224393
  • JVM初探 -JVM内存模型

    Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存...

    哲洛不闹
  • 【JVM】剖析JVM内存模型

      JVM在执行java程序时的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而...

    程序员云帆哥
  • JVM初探 -JVM内存模型

    Tanyboye
  • jvm(1):jvm内存模型

    身为一个职业的Java程序员,每天打交到最多的就是jvm,那么套用孙子的一句话“知己知彼方能百战不殆”,熟悉jvm也就意味着是我们进阶路上必过之槛,下面先来张图...

    yiduwangkai
  • 【Jvm】Jvm类加载机制

    PS: NoClassDeFoundError:发生在类生命周期中解析阶段找不到相应的类 ClassNotFoundException发生在类生命周期的...

    石臻臻的杂货铺[同名公众号]
  • JVM系列(一)—— 何为JVM

    JVM能够跨计算机系结构来执行JAVA字节码,主要是由于JVM屏蔽了与各个计算机平台相关的软件或硬件之间的差异,使得与平台相关的耦合统一由JVM提供者来实现。

    MickyInvQ
  • JVM

    重学Java系列之深入理解JVM虚拟机6:JNDI,OSGI,Tomcat类加载器实现

    hhss
  • JVM

    Java 程序中的内存分配和回收都由 JVM 管理,不支持程序员直接对内存地址进行操作。不容易出现内存泄漏和内存溢出问题。

    Qwe7
  • jvm

    pool_count)。与Java中语言习惯不同,这个容量计数是从1而不是0开始的,如下图所示,常量池容

    Java廖志伟
  • JVM

       JVM是java virtual mechine 的缩写,是在真实的计算机基础上模拟计算机的各种功能的一种实现,JVM的本身对于计算机而言也是一个程序。 ...

    OPice
  • JVM

    JDK 包含 JRE 以及各种 Java 开发工具(如编译器 javac 、调试器 jdb 等)。

    Qwe7
  • jvm系列(二):JVM内存结构

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实...

    纯洁的微笑
  • JVM 《四 JVM 中的String》

    String 这样的量,在我们的认知中是比较特别的。 其中String 是个对象,然后String也可以是个普通的字面量。在每代JDK中对String 的处理...

    邹志全
  • JVM活学活用——Jvm内存结构

    Java内存结构: ? JVM内存结构主要是有三大块:堆内存、方法区和栈。堆内存是JVM中最大的一块由年轻代和老年代组成,而年轻代内存又被分为三部分,Eden空...

    Janti
  • 【java进阶JVM】JVM内存结构

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实...

    用户5640963
  • JVM笔记 -- JVM经历了什么?

    解释器,需要逐行解释执行,效率低下。譬如:如果循环两千次,循环体很大,每次执行都需要解释执行。

    秦怀杂货店
  • JVM笔记 -- JVM经历了什么?

    解释器,需要逐行解释执行,效率低下。譬如:如果循环两千次,循环体很大,每次执行都需要解释执行。

    秦怀杂货店

扫码关注腾讯云开发者

领取腾讯云代金券