字节码

字节码执行引擎知识点总结

◇◆丶佛笑我妖孽 提交于 2020-03-02 22:38:24
以下是在学习了《深入理解JVM》之后的对知识点的总结,其中对方法调用那一章做了大量实践和分析。 文章目录 解释型还是编译型 基于栈还是基于寄存器 字节码指令在哪儿 java虚拟机栈与栈帧的关系 局部变量表 操作数栈 动态连接 方法返回地址 栈帧与方法的关系 字节码指令中的四个方法调用指令 invokevirtual指令解析过程 静态分派,重载,编译期确定 动态分派,重写,运行时确定 解释型还是编译型 字节码的执行有解释型和编译型,根据具体情况才能说明java到底是什么执行方式。 基于栈还是基于寄存器 虚拟机是基于栈的指令集,栈指的是java虚拟机栈,指令集指的字节码指令。 字节码指令在哪儿 执行的字节码指令存放在字节码文件里的方法表里的code属性中。 java虚拟机栈与栈帧的关系 虚拟机栈的基本单位为栈帧,栈帧之间的排列是先进后出。每个栈帧包括了局部变量表,操作数栈,动态连接,方法返回地址以及其他一些信息。 每个栈帧的大小在编译期已经决定,因此栈帧中的每个结构都在编译期确定。 虚拟机栈是线程私有,线程结束栈帧的所有内存都会清除。 局部变量表 局部变量表的单位为slot。 一个slot的大小必须要装的下除long,double类型之外其他基本类型,一般4个字节,也就是32位。 对于long,double类型使用两个slot存放。 局部变量表利用索引来获取值,就如同数组一样

ASMSupport局部变量的实现

只谈情不闲聊 提交于 2020-03-02 11:08:34
#局部变量的实现 git@osc地址 在字节码层面,每一个方法都有一个局部变量数组,用来存储当前方法的参数,在方法内声明的变量,如果是非静态方法还要存储当前方法实例的引用this。在我们平时使用java的时候,这个局部变量的大小是在源码编译成class的时候就确定了的,那么如何更高效的利用这个局部变量,并且合理分配每个变量对应在局部变量数组中的位置呢,下面我们就介绍ASMSupport是如何规划局部变量的,先看下面的代码。 代码1 public void method(boolean bool) { int prefix = 1; if(bool) { double d = 2.12; String s = "string"; ... } else { char c = 'a'; long l = 1L; } } 上面的的代码我们用作用域的方式表现出来如下图: 如果按照程序流程执行,很显然这里会有两种执行结果。分别是当bool为真的时候执行if语句块,当bool为false执行else语句块。如下图就是这两种情况的局部变量图 上面前局部变量中,前三个变量是共享的,发生变化的是第后面的变量,对于这两种执行情况,虽然声明的变量类型不同,并且变量字长是不同的,但是由于if和else两个程序块是并行的,所以局部变量中后三个位置是公用的。根据这种情况

JVM解毒——JVM与Java体系结构

笑着哭i 提交于 2020-03-02 10:53:42
你是否也遇到过这些问题? 运行线上系统突然卡死,系统无法访问,甚至直接OOM 想解决线上JVM GC问题,但却无从下手 新项目上线,对各种JVM参数设置一脸懵逼,直接默认,然后就JJ了 每次面试都要重新背一遍JVM的一些原理概念性东西 这段广告语写的好,趁着在家办公学习下JVM,先列出整体知识点 Java开发都知道JVM是Java虚拟机,上学时还用过的VM也叫虚拟机,先比较一波 虚拟机与Java虚拟机 所谓虚拟机(Virtual Machine),就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。 Visaual Box,VMware就属于系统虚拟机,它们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台 程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令我们称为Java字节码指令 JVM 是什么 JVM 是 Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 Java虚拟机是二进制字节码的运行环境,负责装载字节码到其内部,解释/编译为对应平台的机器指令执行。每一条Java指令,Java虚拟机规范中都有详细定义,如怎么取操作数

[Java] JAVA和JVM运行原理

元气小坏坏 提交于 2020-03-02 04:24:08
个人博客导航页(点击 右侧 链接 即可打开个人博客): 大牛带你入门技术栈 JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器。它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序。 编译器负责把Java程序转成Class文件,方便Jvm来读取它. Jvm是java虚拟机,其实它就是解释器,把Class文件中的命令转成某种平台的命令,比如把Java命令转成Windows下的命令,然后Java程序就执行了. 这里和大家简单分享一下JAVA和JVM运行的原理,Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’(.class文件,也就是0,1二进制程序),然后在OS之上的Java解释器中解释执行,而JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器 JAVA和JVM运行的原理 1.Java语言运行的过程 Java语言写的源程序通过Java编译器,编译成与平台无关的‘字节码程序’(.class文件,也就是0,1二进制程序),然后在OS之上的Java解释器中解释执行。 也相当与 注:JVM(java虚拟机)包括解释器,不同的JDK虚拟机是相同的,解释器不同。 2.JVM: JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器

3 -【 JVM - 动态字节码技术 】

余生颓废 提交于 2020-03-01 22:54:27
1 字节码技术应用场景 AOP 技术 Lombok 去除重复代码插件 动态修改 class 文件等 2 字节技术优势 Java 字节码增强指的是在 Java 字节码生成之后,对其进行修改,增强其功能,这种方式相当于对应用程序的二进制文件进行修改。Java 字节码增强主要是为了减少冗余代码,提高性能等。 实现字节码增强的主要步骤为: 修改字节码 在内存中获取到原来的字节码,然后通过一些工具(如 ASM,Javaasist)来修改它的 byte[] 数组,得到一个新的 byte 数组。 使修改后的字节码生效 有两种方法: 1) 自定义 ClassLoader 来加载修改后的字节码; 2)替换掉原来的字节码:在 JVM 加载用户的 Class 时,拦截,返回修改后的字节码;或者在运行时,使用 Instrumentation.redefineClasses 方法来替换掉原来的字节码 3 常见的字节码操作类库 3.1 BCEL Byte Code Engineering Library (BCEL),这是 Apache Software Foundation 的 Jakarta 项目的一部分。 BCEL 是 Java classworking 广泛使用的一种框架,它可以让您深入 jvm 汇编语言进行类库操作的细节。 BCEL 与 javassist 有不同的处理字节码方法, BCEL

深入剖析Classloader(一)--类的主动使用与被动使用

时光总嘲笑我的痴心妄想 提交于 2020-03-01 21:28:25
原文地址: http://yhjhappy234.blog.163.com/blog/static/3163283220115573911607 我们知道 java 运行的是这样的,首先 java 编译器将我们的源代码编译成为字节码,然后由 JVM 将字节码 load 到内存中,接着我们的程序就可以创建对象了,我们知道 JVM 将字节码 load 到内存之后将将建立内存模型( JVM 的内存模型我们将在稍后阐述),那 JVM 是怎么将类 load 到内存中的呢?对了,是通过 Classloader ,今天我们就来深入探讨一下 Classloader 。 首先我们来看一段诡异的代码(一段单实例测试代码)。 package com.yhj.jvm.classloader; /** * @Description:单例初始化探究 * @Author YHJ create at 2011-6-4 下午08:31:19 * @FileName com.yhj.jvm.classloader.ClassLoaderTest.java */ class Singleton{ private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0;

java内存区域----运行时数据区

别等时光非礼了梦想. 提交于 2020-03-01 16:14:59
Java虚拟机的内存区域也叫做java运行时数据区,共分为五个部分:程序计数器,方法区,本地方法栈,虚拟机栈和堆。方法区和堆是线程之间所共有的,程序计数器,本地方法栈,虚拟机栈是线程私有的。其中虚拟机栈和堆是程序员日常谈论最多也是最关注的一部分。 程序计数器:程序计数器就是指向当前线程要执行的字节码。字节码解释器通过改变这个值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等都需要依赖计数器来完成。每一个线程都拥有一个计数器,互不影响。(注:如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟字节码指令的地址,如果正在执行的是本地方法,这个计数器值为空,此内存区域是唯一一个在《java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域)。通俗点说程序计数器就是用来指示我该执行哪条字节码指令了。 方法区:各个线程共享的内存区域,用于存储被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存,运行时常量池等数据。(注:《java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫“非堆”,目的是与java堆区分开来)。方法区不需要使用连续的内存,可以选择固定大小或者对外扩展,甚至可以选择不实现垃圾收集。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载。运行时常量池是方法区的一部分

yargen工具原理分析

本秂侑毒 提交于 2020-02-29 17:30:52
yara是用来检测恶意软件的利器,yara规则由特征字符串、特征字节码等元素组成,只要恶意软件包含这些特征元素,就说明该文件是恶意的。但一个一个文件提特征是很耗人力的,所以业界就慢慢出现了一些出色的yara自动化提取工具,yarGen便是其中效果比较好的一个,下面,我们就通过分析该工具的源码,来了解这类工具的原理。 项目地址为:https://github.com/Neo23x0/yarGen 核心文件为yarGen.py,其他的文件大多为配置文件。 其中dbs文件夹存放着大量的db文件,这些都是白名单元素,用来过滤特征。包含了白导出函数名、白imphash、白字节码、白字符串。 源码一开始就会下载更新这些db文件,并加载,后面会用到。这是个耗时且耗内存的步骤。 加载完白名单库后,yarGen会初始化一个贝叶斯算法训练器,用于后面机器学习。至此,初始化结束,调用processSampleDir开始提取yara规则。 processSampleDir由3个核心函数组成:parse_sample_dir、sample_string_evaluation、generate_rules,作用分别为:提取样本特征、过滤特征、聚合特征生成yara规则。 第一个函数做了2个操作,从样本中提取字符串,和字节码。 extract_strings只提取6个字符以上的字符串,及包含16进制的字符串。

java内存模型规范学习总结

ぃ、小莉子 提交于 2020-02-29 16:29:17
java内存模型 复习jdk1.7虚拟机规范 了解java内存模型,需要我们对计算机硬件体系有一个基本掌握,要知道计算机里面的内存、高速缓冲、处理器、内存一致协议这些概念。 硬件系统内存模型 现代计算机为了解决处理器与存储设备之间性能冲突,引入了高速缓存,高速缓存读写速度接近处理器运算速度,为处理器单独使用。将运算需要使用到的数据复制到缓存种,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样处理器就不需要等待内存的读写了。 而在多处理器系统中,就涉及到 缓存一致性 问题,每个处理器都有自己的高速缓存,而它们又共享同一主内存。 内存模型:在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程。 java内存模型 不同的物理架构可以拥有不一样的内存模型,而java内存模型就是为了解决各种物理机上内存访问差异而产生的,以实现让java程序在各种平台下达到一致的内存访问效果。 java内存模型的目标,是定义程序中各个变量的访问规则,即在虚拟机中将变量的存储到内存和从内存中取出变量这样的底层细节。 java内存模型规定所有的变量都存储在主内存。 线程拥有自己的工 作内存,保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作必须在工作内存中完成,不能直接操作主内存。 不同的线程不能直接访问对方的工作内存中变量,线程间变量值传递必须通过主内存来完成。

13函数基础

て烟熏妆下的殇ゞ 提交于 2020-02-29 00:00:05
1.1 快速体验 所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用 函数的使用包含两个步骤: 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的 重用 演练步骤 新建 04_函数 项目 复制之前完成的 乘法表 文件 修改文件,增加函数定义 multiple_table(): 新建另外一个文件,使用 import 导入并且调用函数 函数基本使用 2.1 函数的定义 定义函数的格式如下: def 函数名(): 函数封装的代码 …… def 是英文 define 的缩写 函数名称 应该能够表达 函数封装代码 的功能,方便后续的调用 函数名称 的命名应该 符合 标识符的命名规则 可以由 字母、下划线 和 数字 组成 不能以数字开头 不能与关键字重名 2.2 函数调用 调用函数很简单的,通过 函数名() 即可完成对函数的调用 2.3 第一个函数演练 需求 编写一个打招呼 say_hello 的函数,封装三行打招呼的代码 在函数下方调用打招呼的代码 name = "小明" # 解释器知道这里定义了一个函数 def say_hello ( ) : print ( "hello 1" ) print ( "hello 2" ) print ( "hello 3" ) print (