美文网首页
java类文件

java类文件

作者: 7d972d5e05e8 | 来源:发表于2019-12-12 22:47 被阅读0次

一、定义

  1. 虚拟机栈

虚拟机栈代表是线程维度,一个线程有且只有一个虚拟栈。虚拟机栈存储的单位是栈帧,而一个栈帧包含了:局部变量表、操作数栈、动态链接、方法出口等信息。正在的字节码计算,出栈入栈可不再虚拟机栈上噢。虚拟机栈仅仅是用来保存该线程,所调用所有的方法。每次在调用方法的时候,肯定会先初始化方法的栈帧,然后入虚拟机栈。

  1. 操作数栈

java类的一个方法,可以看做是一个操作数栈。一定要和虚拟机栈区分开。操作数栈仅仅是虚拟机栈保存的栈帧,且还是栈帧中一小块数据而已。表示一个完成方法执行运行时栈。方法的所有字节码操作,都是在这个栈帧中出栈和入栈。

二、java源码的编译过程

  1. 过程

词法分析 -> 语法分析 -> 语义分析 -> 数据/控制流分析 -> 解语法糖 -> 生成字节码

  1. java泛型是由语法糖实现的,即是编译器实现的,不是虚拟机实现。因为,还没到虚拟机这层。虽然在编译阶段,编译器会把泛型擦除,塞上原始类型,但是泛型的类型信息还是被保存在方法code属性中。反射的时候,可以通过方法签名Signature,得到泛型的具体类型信息。比如:List<String>在编译的时候,会被擦除为List<E>,但是code属性中,通过Signature可以得到其泛型类型为String类型。

三、java方法区

https://blog.csdn.net/dshf_1/article/details/87171171

java方法区存储的类对象(非实例对象)结构,如下:


image.png

java中的所有类都是已oop-klass为设计基础的

四、破坏双亲委派模型的应用场景

4.1 JDBC为什么要破坏双亲委派模型

java rt.jar中的系统类,通过SPI加载用户路径下的实现类。是通过Thead.getContextClassLoader,来破坏双亲委派模式加载的。
比如:rt.jar中的JDBC、JNDI、JBI等框架,java只是定义规范接口,具体实现由厂商来。在应用执行到JDBC里面的代码时,发现了一个SPI接口,那么接口实现类的加载器就要从Thread取了。根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。发现当前类加载是Root加载器,根本无法加载厂商的类。

JDBC的Driver接口定义在JDK中,其实现由各个数据库的服务商来提供,比如MySQL驱动包。DriverManager 类中要加载各个实现了Driver接口的类,然后进行管理,但是DriverManager位于JAVA_HOME中jre/lib/rt.jar 包,由BootStrap类加载器加载,而其Driver接口的实现类是位于服务商提供的 Jar 包,根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。也就是说BootStrap类加载器还要去加载jar包中的Driver接口的实现类。我们知道,BootStrap类加载器默认只负责加载 JAVA_HOME中jre/lib/rt.jar 里所有的class,所以需要由子类加载器去加载Driver实现,这就破坏了双亲委派模型。

查看DriverManager类的源码,看到在使用DriverManager的时候会触发其静态代码块,调用 loadInitialDrivers() 方法,并调用ServiceLoader.load(Driver.class) 加载所有在META-INF/services/java.sql.Driver 文件里边的类到JVM内存,完成驱动的自动加载。

这个子类加载器是通过 Thread.currentThread().getContextClassLoader() 得到的线程上下文加载器。如下:

public Launcher() {
    ...
    try {
        this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
    } catch (IOException var9) {
        throw new InternalError("Could not create application class loader", var9);
    }
    Thread.currentThread().setContextClassLoader(this.loader);
    ...
}

4.2 Tomcat为什么要破坏双亲委派模型

Tomcat如何破坏双亲委派模型的呢?

每个Tomcat的webappClassLoader加载自己的目录下的class文件,不会传递给父类加载器。

事实上,tomcat之所以造了一堆自己的classloader,大致是出于下面三类目的:

  • 对于各个 webapp中的 classlib,需要相互隔离,不能出现一个应用中加载的类库影响另一个应用的情况,而对于许多应用,需要有共享的lib以便不浪费资源。
  • jvm一样的安全性问题。使用单独的 classloader去装载 tomcat自身的类库,以免其他恶意或无意的破坏;
  • 热部署。相信大家一定为 tomcat修改文件不用重启就自动重新装载类库而惊叹吧。

五、java实例字段的访问

比如有个Person类有两个字段name和age,Man继承Person,有个gender字段。那么man对象是怎么访问字段的呢?java语法上,没啥好说的,直接getName或者man.name都能访问到。那么在JVM或者内存层面,怎么访问的呢?

  1. 首先我们要搞清楚,man对象存储的是啥?Man man = new Man("张三",20,"男性")。这段代码在执行的时候,就是对象创建的过程。这里就不多介绍了。只要知道结果是:在内存中开辟了一段连续地址,字段顺序按照规则依次排好。内存中通过utf-16,储存的是文本二进制。为啥用utf-16,可以参考:Java 为什么使用 UTF-16 而不是更节省内存的 UTF-8
  2. 既然知道了man对象的数据在内存中怎么存储的,那么是不是就知道了应该怎么取出来。比如man.name,jvm根据步骤1中的顺序从内存中拿出来,然后解码后就是结果了。

相关文章

  • 第十五章文件与流

    JAVA程序如何访问文件属性 java.io.File类 File类访问文件属性 java中的文件及目录处理类 1...

  • 热修复类加载项目实战

    android 与 java 的类加载器 类别加载文件类加载器分类java.class 文件{{java类加载机制...

  • 从字节码角度剖析Java类文件

    1 Java类文件简析 所谓 Java 类文件,就是通常用 javac 编译器产生的 .class 文件。这些文件...

  • 深入理解Class文件-1

    什么是class文件   Java字节码类文件(.class)是Java编译器编译Java源文件(.java)产生...

  • Java运行时数据区笔记

    Java程序执行过程 Java源文件 -> 解析器 -> Class文件 -> Java类加载器 -> Java运...

  • Java知识点汇总

    类 在Java中,类文件是以.java为后缀的代码文件 在每个类文件中最多只允许出现一个public类,当有pub...

  • Java入门系列-22-IO流

    File类的使用 Java程序如何访问文件?通过 java.io.File 类 使用File类需要先创建文件对象 ...

  • Java类加载机制

    Java类加载机制 类编译 类编译,即 .java 文件通过javac命令编译成 .class 文件,才能在虚拟机...

  • Proguard首次学习

    参考 简介 可以对java类文件(不只是java语言生成的java类文件奥),进行压缩,优化,混淆,预校验。 压缩...

  • javaClass类文件结构,类加载过程以及内存分配

    知识要点: Java虚拟机简介 Class类文件结构 Class类文件结构详解 Java虚拟机简介 Java虚拟机...

网友评论

      本文标题:java类文件

      本文链接:https://www.haomeiwen.com/subject/orjdictx.html