JVM_Class文件格式示例
JavaClass类解析

1.Class对象Class对象包含了与类相关的信息。
事实上,Class对象就是用来创建类的所有的“普通”对象的。
类是程序的一部分,每个类都有一个Class对象。
换言之,每当编写并且编译了一个新类,就会产生一个Class对象(恰当地说,是被保存在一个同名的.class文件中)。
在运行时,当我们想生成这个类的对象时,运行这个程序的Java虚拟机(JVM)首先检查这个类的Class对象是否已经加载。
如果尚未加载,JVM就会根据类名查找.class文件,并将其载入。
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。
看下面示例。
SweetShop.javapackage com.zj.sample;class Candy {static {System.out.println("Loading Candy");}}class Gum {static {System.out.println("Loading Gum");}}class Cookie {static {System.out.println("Loading Cookie");}}public class SweetShop {public static void main(String[] args) {System.out.println("inside main");new Candy();System.out.println("After creating Candy");try {Class.forName("com.zj.sample.Gum");} catch (ClassNotFoundException e) {System.out.println("Couldn't find Gum");}System.out.println("After Class.forName(\"Gum\")");new Cookie();System.out.println("After creating Cookie");}}结果:Loading CandyAfter creating CandyLoading GumAfter Class.forName("Gum")Loading CookieAfter creating Cookie2.获取Class实例的三种方式1)利用对象调用getClass()方法获取该对象的Class实例。
jvm 参数格式

jvm 参数格式(实用版)目录1.JVM 参数简介2.JVM 参数格式3.常见 JVM 参数及其作用4.JVM 参数配置方法5.总结正文1.JVM 参数简介JVM(Java 虚拟机)是 Java 语言的核心组件,负责管理 Java 程序的运行。
在 Java 程序运行过程中,JVM 会根据程序的需求和系统资源进行必要的调整,以保证程序的稳定运行。
这些调整通常通过 JVM 参数来实现。
2.JVM 参数格式JVM 参数采用键值对(key-value)的形式进行配置,其中键表示参数的名称,值表示参数的值。
参数名和值的格式通常为:```参数名=参数值```多个参数之间用空格分隔,如:```-Xmx2g -Xms1g```3.常见 JVM 参数及其作用以下是一些常见的 JVM 参数及其作用:-Xms:初始堆内存大小。
指定 Java 程序启动时堆内存的初始大小。
-Xmx:最大堆内存大小。
指定 Java 程序运行过程中堆内存允许达到的最大值。
-Xmn:年轻代堆内存大小。
指定年轻代堆内存的大小。
-Xss:栈空间大小。
指定每个线程的栈空间大小。
-XX:+UseComcSpin:使用自旋锁。
开启此参数可以提高多线程程序的性能。
-XX:+UseConcMarkSweepGC:使用并发标记清除垃圾收集器。
开启此参数可以提高垃圾回收的效率。
4.JVM 参数配置方法JVM 参数可以通过以下几种方法进行配置:-在启动 Java 程序时,通过命令行参数的形式指定。
如:```java -Xmx2g -Xms1g -XX:+UseComcSpin -XX:+UseConcMarkSweepGC YourMainClass```-在 Java 程序代码中,通过`System.getProperty()`方法获取参数值。
如:```javaString xmx = System.getProperty("Xmx");```-在 Java 程序的 JVM 启动参数配置文件(如:jvm.config)中指定。
class文件直接修改_反编译修改class文件变量

class⽂件直接修改_反编译修改class⽂件变量今天笔者同事遇到⼀个问题,客户同事的数据库连接信息直接写在代码中,连接的密码改了,但是⼜没有源代码,所以只能直接修改Java class⽂件。
记录⼀下修改步骤:1.下载JClassLib_windows(后⾯⽤到),下载jd-gui-1.4.0.jar,⽤来反编译class⽂件的,IDEA也可以反编译class⽂件;找到需要修改⽂件的变量,我这⾥是Admin。
2.第⼆步把class⽂件,备份待⽤,把⼯程⽂件存⼀份,⽅法如下图所⽰:3.安装JClassLib,安装完成之后⽤JClassLib打开需要修改的class⽂件,我这⾥是Client.class,找到需要修改的函数⽅法位置,我这⾥是main函数,然后点菜单的code,查看右侧的Bytecode,找到需要修改的变量Admin,然后点击#173,会跳到变量区,如下⾯⼆张图说明: 图1图2 4.⿏标点击cp_info#174会跳转到174这⾏变量,如下图所⽰:4.替换变量写⼀个Java程序,替换指定变量的值,filePath变量存在需要替换的class⽂件路径,174是需要替换的位置,Admin123是希望替换的变量,如果替换成中⽂需要注意⽬标编码(不然会⽤JVM默认编码),如下图所⽰:图1图2 中⽂编码设置4.上⾯的Java程序完整代码如下,特别需要注意的是:程序依赖JClasslib包下的jclasslib-library.jar包,所以可以进到JClasslib安装路径下拷贝⼀个jclasslib-library.jar包⽂件放到build path内,我的路径和jar包⽂件如下:完整代码,你们替换三处,⽂件路径、变量位置、修改后⽬标变量import java.io.DataInput;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import org.gjt.jclasslib.io.ClassFileWriter;import org.gjt.jclasslib.structures.CPInfo;import org.gjt.jclasslib.structures.ClassFile;import org.gjt.jclasslib.structures.InvalidByteCodeException;import org.gjt.jclasslib.structures.constants.ConstantUtf8Info; public class Client{@SuppressWarnings("deprecation")public static void main(String[] args){String filePath = "C:\\Users\\zw\\Desktop\\Client.class";FileInputStream fis = null;try {fis = new FileInputStream(filePath);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}DataInput di = new DataInputStream(fis);ClassFile cf = new ClassFile();try {cf.read(di);} catch (InvalidByteCodeException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}CPInfo[] infos = cf.getConstantPool();int count = infos.length;for (int i = 0; i < count; i++) {if (infos[i] != null) {System.out.print(i);System.out.print(" = ");try {System.out.print(infos[i].getVerbose());} catch (InvalidByteCodeException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.print(" = ");System.out.println(infos[i].getTagVerbose());if(i == 174){ConstantUtf8Info uInfo = (ConstantUtf8Info)infos[i]; uInfo.setBytes("Admin123".getBytes());infos[i]=uInfo;}}}cf.setConstantPool(infos);try {fis.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}File f = new File(filePath);try {ClassFileWriter.writeToFile(f, cf);} catch (InvalidByteCodeException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}另外我把⼯程。
class,classloder,dex详解

class,classloder,dex详解class与dex⽂件什么是class⽂件class⽂件是⼀种能够被JVM识别,加载并且执⾏的⽂件格式。
class⽂件的作⽤class⽂件的作⽤是记录⼀个类⽂件的所有信息。
例如记住了当前类的引⽤this、⽗类super等等。
class⽂件记录的信息往往⽐java⽂件多。
class⽂件的结构8位字节的⼆进制流⽂件各个数据紧密排列,⽆间隙,减少了⽂件体积,加快加载速度每个类或者接⼝单独占据⼀个class⽂件,每个类单独管理,没有交叉class⽂件的弊端内存占⽤⼤,不适合于移动端堆栈的加载模式导致加载速度慢⽂件IO操作多,类查找慢什么是dex⽂件能够被DVM或者Art虚拟机执⾏并且加载的⽂件格式。
dex⽂件的作⽤dex⽂件的作⽤是记录整个⼯程(通常是⼀个Android⼯程)的所有类⽂件的信息。
dex⽂件的结构8位字节的⼆进制流⽂件各个数据紧密排列,⽆间隙,减少了⽂件体积,加快加载速度整个⼯程的类信息都存放在⼀个dex⽂件中(不考虑dex分包的情况下)class⽂件与dex⽂件的⽐较本质上都是⼀样的,都是⼆进制流⽂件格式,dex⽂件是从class⽂件演变⽽来的class⽂件存在冗余信息,dex⽂件则去掉了冗余,并且整合了整个⼯程的类信息。
结构对⽐图如下:类加载机制是做热修复以及插件化的很重要的理论基础。
Java中的ClassLoader回顾如下图所⽰:ClassLoader的特性ClassLoader的主要特性是双亲委托机制,即加载⼀个类的时候,先判断已经存在的类是否被加载过,如果没有,先去委托⽗亲去加载。
如果⽗亲都没有加载成功的话,那么最终由⾃⼰加载。
最终这个类最终没有合适的CLassLoader加载,那么就会抛出异常,相关的ClassLoader源码如下:protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{// 先判断这个类是否已经被加载过Class c = findLoadedClass(name);if (c == null) {// 如果没有被加载过,那么委托⽗亲去加载long t0 = System.nanoTime();try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}// 如果⽗亲没有加载,那么最终由⾃⼰(实现类)负责加载if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the stats}}return c;}其中CLassLoader的findClass⽅法是空实现,需要⾃⼰继承然后实现:protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name);}这种双亲委托机制有两种好处:1. 实现类加载的共享功能,提升类加载的效率。
JVM 之 Class文件资料结构

JVM 之Class文件结构本文写作目的:1)为了加深自己学习的理解,2)帮助正在学习研究JVM的,3)与任何热爱技术的达人交流经验,提升自己以此为本,文章会尽量写的简洁,尽量保证理解的正确性,如有任何理解不到位或错误的地方,希望朋友们及时指出,严厉拍砖。
开始之前我们需要先了解一些基本的概念,这些概念是学习整个JVM原理的基础。
1)JVM虚拟机规主要规了Class文件结构,虚拟机存结构,虚拟机加载,解析,执行Class文件的行为方式,以及一系列的字节码指令集。
2)Class文件理论上说是一种数据结构,该数据结构有着严格的格式规,该规在字节粒度上规定了组成该数据结构的格式标准。
3)Class文件本质上是一组二进制字节流,是被JVM解析执行的数据源,每个字节都有着不同的含义,可能表示字符,数字,也可能表示执行某种操作的一个字节码指令。
4)JVM (Java 虚拟机)是解析执行Class文件的核心引擎,是整个Java系统的运行时环境,是跨平台的基石。
5)我们的Java代码需要被编译器编译成完整,正确的Class文件才能被JVM正确的执行。
6)编译器并非JVM的一部分,不同的语言可以提供不同的编译器,其作用是将该语言的代码编译为正确的Class文件,如Scala,JRuby等等。
7)JVM是完全开放的跨平台的,只要你有能力你可以按照JVM虚拟机规编写自己的编程语言。
8)JVM 使得Java的跨平台成为可能,那么Class文件结构规则使得更多的编程语言运行在JVM上成为可能。
既然Class文件是一种数据结构,那么到底是什么样的数据结构呢?通常计算机中的文件都包含元数据和实体数据两部分,元数据用来存储该文件的描述信息,实体数据来存放用于表达文件真实容的数据。
当然Class文件也不例外,我们为了便于理解,也将class文件的结构分为两大部分:元数据和实体数据(注:非规定义,只是为了方便理解进行的自定义)。
元数据:包含了Class文件的魔术数(标识符)和版本信息。
运行java的class文件方法详解

运⾏java的class⽂件⽅法详解⼀、运⾏class⽂件执⾏带main⽅法的class⽂件,命令⾏为:java <CLASS⽂件名>注意:CLASS⽂件名不要带⽂件后缀.class例如:复制代码代码如下:java Test如果执⾏的class⽂件是带包的,即在类⽂件中使⽤了:package <包名>那应该在包的基路径下执⾏,命令⾏为:java <包名>.CLASS⽂件名例如:PackageTest.java中,其包名为:com.ee2ee.test,对应的语句为:package com.ee2ee.test;PackageTest.java及编译后的class⽂件PackageTest.class的存放⽬录如下:classes|__com|__ee2ee|__test|__PackageTest.java|__PackageTest.class要运⾏PackageTest.class,应在classes⽬录下执⾏:复制代码代码如下:java com.ee2ee.test.PackageTest⼆、运⾏jar⽂件中的class原理和运⾏class⽂件⼀样,只需加上参数-cp <jar⽂件名>即可。
例如:执⾏test.jar中的类com.ee2ee.test.PackageTest,命令⾏如下:复制代码代码如下:java -cp test.jar com.ee2ee.test.PackageTest三、显⽰jdk版本信息当⼀台机器上有多个jdk版本时,需要知道当前使⽤的是那个版本的jdk,使⽤参数-version即可知道其版本,命令⾏为:复制代码代码如下:java -version四、增加虚拟机可以使⽤的最⼤内存java虚拟机可使⽤的最⼤内存是有限制的,缺省值通常为64MB或128MB。
如果⼀个应⽤程序为了提⾼性能⽽把数据加载内存中⽽占⽤较⼤的内存,⽐如超过了默认的最⼤值128MB,需要加⼤java虚拟机可使⽤的最⼤内存,否则会出现Out of Memory(系统内存不⾜)的异常。
java程序来解析class文件,实现反编译

[B01][java程序解析class文件]Type:[B01][Solution]Submit:[abc@][2012.11.06][V1.00]From:/jtf975/blog/static/18135128720112612517429/我们都知道,Java编译器负责将.java文件编译成.class文件,class文件存储的是java字节码,与.java 文件无关(只要你愿意写一个编译器,也可以将别的语言写的源代码编译成.class文件),本文预备具体解剖class文件的内部结构,并且把class文件结构读取并显示出来。
Class文件的格式由JVM规范规定,一共有以下部分:1. magic number,必须是0xCAFEBABE,用于快速识别是否是一个class文件。
2. version,包括major和minor,假如版本号超过了JVM的识别范围,JVM将拒尽执行。
3. constant pool,常量池,存放所有用到的常量。
4. access flag,定义类的访问权限。
5. this class和super class,指示如何找到this class和super class。
6. inte***ces,存放所有inte***ces。
7. fields,存放所有fields。
8. methods,存放所有methods。
9. attributes,存放所有attributes。
先写一个Test.java:package example.test;public final class TestClass {public int id = ;public void test() {}}公司地址:北京海淀区彩和坊路10号1+1大厦3层100080然后编译,放在C:\Documents and Settings\Administrator\桌面\解析class文件\TestClass.java。
描述一下JVM加载class文件的原理机制

描述⼀下JVM加载class⽂件的原理机制Java中的所有类,都需要由类加载器装载到JVM中才能运⾏。
类加载器本⾝也是⼀个类,⽽它的⼯作就是把class⽂件从硬盘读取到内存中。
在写程序的时候,我们⼏乎不需要关⼼类的加载,因为这些都是隐式装载的,除⾮我们有特殊的⽤法,像是反射,就需要显式的加载所需要的类。
类装载⽅式,有两种:1.隐式装载,程序在运⾏过程中当碰到通过new 等⽅式⽣成对象时,隐式调⽤类装载器加载对应的类到jvm中,2.显式装载,通过class.forname()等⽅法,显式加载需要的类Java类的加载是动态的,它并不会⼀次性将所有类全部加载后再运⾏,⽽是保证程序运⾏的基础类(像是基类)完全加载到jvm 中,⾄于其他类,则在需要的时候才加载。
这当然就是为了节省内存开销。
Java的类加载器有三个,对应Java的三种类:Bootstrap Loader :启动类加载器,是虚拟机⾃⾝的⼀部分。
负责将存放在\lib⽬录中的类库加载到虚拟机中。
其⽆法被Java程序直接引⽤。
负责加载系统类 (指的是内置类,像是String,对应于C#中的System类和C/C++标准库中的类) ExtClassLoader :负责加载扩展类(就是继承类和实现类)AppClassLoader :负责加载⽤户类路径(ClassPath)上所指定的类库(程序员⾃定义的类)JVM中类的加载是由类加载器(ClassLoader)和它的⼦类来实现的,Java中的类加载器是⼀个重要的Java运⾏时系统组件,它负责在运⾏时查找和装⼊类⽂件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是⼀个可执⾏程序,⽽是⼀个或多个类⽂件。
当Java程序需要使⽤某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class⽂件中的数据读⼊到内存中,通常是创建⼀个字节数组读⼊.class⽂件,然后产⽣与所加载类对应的Class对象。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.环境JDK 1.6.0_10-rc22.源代码/*** 验证java class类格式* 以下代码不要修改:* @author: zhanglixin* @version: 1.0 2013-1-10*/public class ClassFormat1 implements Serializable{final int C=8;final String S="Hello!";private double instaneDouble=1.01;static double staticDouble = 2.02;public static void main(String[] args){boolean localBln = true;}}3.编译后字节码通过javap -version 查看E:\testspace\jvm>javap -verbose ClassFormat1Compiled from "ClassFormat1.java"public class ClassFormat1 extends ng.Object implements java.io.Serializable SourceFile: "ClassFormat1.java"minor version: 0major version: 50Constant pool:const #1 = Method #12.#32; // java/lang/Object."<init>":()V const #2 = Field #11.#33; // ClassFormat1.C:Iconst #3 = String #34; // Hello!const #4 = Field #11.#35; // ClassFormat1.S:Ljava/lang/String; const #5 = double 1.01d;const #7 = Field #11.#36; // ClassFormat1.instaneDouble:D const #8 = double 2.02d;const #10 = Field #11.#37; // ClassFormat1.staticDouble:D const #11 = class #38; // ClassFormat1const #12 = class #39; // java/lang/Objectconst #13 = class #40; // java/io/Serializableconst #14 = Asciz C;const #15 = Asciz I;const #16 = Asciz ConstantValue;const #17 = int 8;const #18 = Asciz S;const #19 = Asciz Ljava/lang/String;;const #20 = Asciz instaneDouble;const #21 = Asciz D;const #22 = Asciz staticDouble;const #23 = Asciz <init>;const #24 = Asciz ()V;const #25 = Asciz Code;const #26 = Asciz LineNumberTable;const #27 = Asciz main;const #28 = Asciz ([Ljava/lang/String;)V;const #29 = Asciz <clinit>;const #30 = Asciz SourceFile;const #31 = Asciz ClassFormat1.java;const #32 = NameAndType #23:#24;// "<init>":()Vconst #33 = NameAndType #14:#15;// C:Iconst #34 = Asciz Hello!;const #35 = NameAndType #18:#19;// S:Ljava/lang/String;const #36 = NameAndType #20:#21;// instaneDouble:Dconst #37 = NameAndType #22:#21;// staticDouble:Dconst #38 = Asciz ClassFormat1;const #39 = Asciz java/lang/Object;const #40 = Asciz java/io/Serializable;{final int C;Constant value: int 8final ng.String S;Constant value: String Hello!static double staticDouble;public ClassFormat1();Code:Stack=3, Locals=1, Args_size=10: aload_01: invokespecial #1; //Method java/lang/Object."<init>":()V 4: aload_05: bipush 87: putfield #2; //Field C:I10: aload_011: ldc #3; //String Hello!13: putfield #4; //Field S:Ljava/lang/String;16: aload_017: ldc2_w #5; //double 1.01d20: putfield #7; //Field instaneDouble:D 23: returnLineNumberTable:line 37: 0line 38: 4line 39: 10line 40: 16public static void main(ng.String[]);Code:Stack=1, Locals=2, Args_size=10: iconst_11: istore_12: returnLineNumberTable:line 44: 0line 45: 2static {};Code:Stack=2, Locals=0, Args_size=00: ldc2_w #8; //double 2.02d3: putstatic #10; //Field staticDouble:D 6: returnLineNumberTable:line 41: 0}4.class文件分析0X00000000h 偏移0-3:魔法数字。
0X00000000h 偏移4-5:次版本号。
0X00000000h 偏移5-6:主版本号。
0X00000000h 偏移8-9:常量池个数。
算法:16进制转换为10进制-1。
0X29:41-1个常量。
0X00000000h 偏移A 至0X00000160h 偏移8:常量池。
0X00000160h 偏移9-A:Access flag类访问修饰符0X00000160h 偏移B-C:当前类名字索引0X00000160h 偏移D-E:父类名字索引0X00000160h 偏移F- 0X00000170h 偏移0 :该类实现的接口数量。
值00 001,1个。
0X00000170h 偏移1-2:接口名字索引。
值00 0D,索引值13.即对应常量池索引号13的项,即该接口名字。
0X00000170h 偏移3- 至0X00000200 偏移4:为域Field的信息0X00000170h 偏移3-4 :域的数量。
值00 04,即4个域。
0X00000170h 偏移5-6 :第一个域的访问修饰(Access Flag),值:00 10,即ACC_FINAL,final方法,不可覆盖。
0X00000170h 偏移7-8 :域名字索引。
值00 0E,即对应常量池第14项,即“C”,域的名字为C 。
0X00000170h 偏移9-a :域名字的描述符。
值00 0F,即对应常量池第15项,即“I”,域的类型为Integter 整型。
0X00000170h 偏移b-c :该域所含属性的数量。
值00 01,含有一个属性。
0X00000170h 偏移d-e :该属性的名字索引。
值00 10,即对应常量池16项,即:ConstantValue.该属性值为常量值。
0X00000170h 偏移f- 0X00000180h 偏移2 :属性的长度,值00 00 00 02,即4个字节长。
0X00000180h 偏移3-4:属性值00 11,即对应常量池的索引是17,为:“int 8”。
以下各个域相同。
0X00000180h 偏移5 至0X00000190 偏移4 :第二个域final String S="Hello!"的域。
0X00000190h 偏移5 至0X00000190 偏移c :第三个域private double instaneDouble=1.01 的域。
注意该域没有属性集合。
0X00000190h 偏移d 至0X000001a0 偏移4 :第四个域static double staticDouble = 2.02 的域。
注意该域没有属性集合。
0X000001a0 偏移5 - 0X00000240h 偏移0 :为方法method的信息。
0X000001a0h 偏移5-6 :方法的数量。
值00 03,即3个方法。
0X000001a0h 偏移7-8 :第一个方法的访问修饰(Access Flag),值:00 01,即ACC_PUBLIC,public方法。
0X000001a0h 偏移9-a :方法名字索引。
值00 17,即对应常量池第23项,即“<init>”,对象实例初始化方法。
0X000001a0h 偏移b-c :方法名字的描述符。
值00 18,即对应常量池第24项,即“()V",方法的参数为空,返回值void。
0X000001a0h 偏移d-e :该方法所含属性的数量。
值00 01,含有一个属性。
0X000001a0h 偏移f- 0X000001b0h 偏移0:该属性的名字索引。
值00 19,即对应常量池25项,即:"Code".该属性值为代码。
0X000001b0h 偏移1-4 :属性的长度,值00 00 00 3c,4个字节长,该属性的长度,3c,即60字节(单位u1),后续60个字节为属性值。