java字节码操作

深入理解 Java 字节码操作码 Java字节码是Java源代码编译后生成的中间表示形式,由Java虚拟机(JVM)执行,确保平台的无关性。字节码由操作码(opcode)组成,每个操作码是一个单字节指令,定义了JVM的执行行为。操作码分为多个家族,如加载/存储、算术、执行控制、方法调用和平台操作等,分别负责不同的功能。理解操作码对于深入掌握Java运行机制、性能优化、调试和字节码操纵(如使用ASM或Javassist)至关重要。本文详细介绍了Java字节码操作码的结构、主要家族及其应用,并通过示例展示了其实际效果,建议开发者使用javap工 阅读详情

动态编译Java源文件:
主要作用就是可以动态的编译生成一些class文件,源码你可以自己拼写。

demo:

package com.partner4java.javacompiler;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

/**
 * 动态编译
 * 
 */
public class CompilerTest {

	public static void main(String[] args) throws Exception {
		// 类的文本
		String source = "public class Main { public static void main(String[] args) {System.out.println(\"Hello World! \");} }";

		// 为 JavaFileObject 中的大多数方法提供简单实现。应子类化此类并用作 JavaFileObject 实现的基础。
		// 子类可以重写此类任意方法的实现和规范,只要不违背 JavaFileObject 的常规协定。
		SimpleJavaFileObject sourceObject = new CompilerTest.StringSourceJavaObject(
				"Main", source);

		// 为查找工具提供者提供方法,例如,编译器的提供者。
		// 获取此平台提供的 Java 编程语言编译器。
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

		// 为此工具获取一个标准文件管理器实现的新实例。
		StandardJavaFileManager fileManager = compiler.getStandardFileManager(
				null, null, null);

		Iterable<? extends JavaFileObject> fileObjects = Arrays
				.asList(sourceObject);

		// 使用给定组件和参数创建编译任务的 future。
		CompilationTask task = compiler.getTask(null, fileManager, null, null,
				null, fileObjects);
		boolean result = task.call();
		if (result) {
			System.out.println(" 编译成功。");
		}
	}

	/**
	 * 主要指定了编译的存储位置和格式
	 *
	 */
	static class StringSourceJavaObject extends SimpleJavaFileObject {

		private String content = null;

		public StringSourceJavaObject(String name, String content)
				throws URISyntaxException {
			super(URI.create("string:///" + name.replace('.', '/')
					+ Kind.SOURCE.extension), Kind.SOURCE);
			this.content = content;
		}

		public CharSequence getCharContent(boolean ignoreEncodingErrors)
				throws IOException {
			return content;
		}
	}
}

是在字节码生成之后对其修改,增强其功能。

CGLIB hellowrld:
http://blog.youkuaiyun.com/partner4java/article/details/7627527

基本都类似于这种做法。



java.lang.instrument:
提供允许 Java 编程语言代理检测运行在 JVM 上的程序的服务。

jdk提供的合法的AOP

两个比较牛B的技术帖子:
http://www.ibm.com/developerworks/cn/java/j-lo-instrumentation/
http://www.ibm.com/developerworks/cn/java/j-cwt06075/

http://blog.sina.com.cn/s/blog_605f5b4f0100qfvc.html

package com.partner4java.instrument;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class MyLog implements ClassFileTransformer {

    // 方法。通过这个方法,代理可以得到虚拟机载入的类的字节码(通过 classfileBuffer
    // 参数)。代理的各种功能一般是通过操作这一串字节码得以实现的。同时还需要提供一个公共的静态方法:
    @Override
    public byte[] transform(ClassLoader loader, String className,
            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
            byte[] classfileBuffer) throws IllegalClassFormatException {
        // transform 函数的最后,返回 null 值,表示不需要进行类字节码的转化
        System.out.println("Hello,\t" + className);
        return null;
    }

    // 一般会在这个方法中创建一个代理对象,通过参数 inst 的 addTransformer()
    // 方法,将创建的代理对象再传递给虚拟机。这个方法是一个入口方法,有点类似于一般类的 main 方法。
    public static void premain(String agentArgs, Instrumentation inst) {
        // options 参数是通过命令行传递进来的,类似于调用 main 函数时传递的参数。被传递进来的命令行参数是一个完整的字符串,不同于
        // main 方法,该字符串的解析完全由代理自己负责。

        // 定制完代理的行为之后,创建一个 MyLog 代理的实例,将该实例传递给虚拟机。
        if (agentArgs != null) {
            System.out.printf("  I've been called with options: \"%s\"\n",
                    agentArgs);
        } else
            System.out.println("  I've been called with no options.");
        inst.addTransformer(new MyLog());
    }

}



maven打包如com.partner4java.javautil.codemanage-0.0.1-SNAPSHOT.jar,然后
C:\Users\Administrator>java -javaagent:E:\partner4java\code\workspace\java字节码
操作\target\com.partner4java.javautil.codemanage-0.0.1-SNAPSHOT.jar="hello world
" com.partner4java.javacompiler.CompilerTest


打印运行时间demo:
com.partner4java.instrument.Timing

package com.partner4java.instrument;

import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.Type;

public class Timing implements ClassFileTransformer {

	private String methodName;

	private Timing(String methodName) {
		this.methodName = methodName;
		System.out.println(methodName);
	}

	public byte[] transform(ClassLoader loader, String className, Class cBR,
			java.security.ProtectionDomain pD, byte[] classfileBuffer)
			throws IllegalClassFormatException {
		try {
			ClassParser cp = new ClassParser(new java.io.ByteArrayInputStream(
					classfileBuffer), className + ".java");
			JavaClass jclas = cp.parse();
			ClassGen cgen = new ClassGen(jclas);
			Method[] methods = jclas.getMethods();
			int index;
			for (index = 0; index < methods.length; index++) {
				if (methods[index].getName().equals(methodName)) {
					break;
				}
			}
			if (index < methods.length) {
				addTimer(cgen, methods[index]);
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				cgen.getJavaClass().dump(bos);
				return bos.toByteArray();
			}
			System.err.println("Method " + methodName + " not found in "
					+ className);
			System.exit(0);

		} catch (IOException e) {
			System.err.println(e);
			System.exit(0);
		}
		return null; // No transformation required
	}

	private static void addTimer(ClassGen cgen, Method method) {

		// set up the construction tools
		InstructionFactory ifact = new InstructionFactory(cgen);
		InstructionList ilist = new InstructionList();
		ConstantPoolGen pgen = cgen.getConstantPool();
		String cname = cgen.getClassName();
		MethodGen wrapgen = new MethodGen(method, cname, pgen);
		wrapgen.setInstructionList(ilist);

		// rename a copy of the original method
		MethodGen methgen = new MethodGen(method, cname, pgen);
		cgen.removeMethod(method);
		String iname = methgen.getName() + "_timing";
		methgen.setName(iname);
		cgen.addMethod(methgen.getMethod());
		Type result = methgen.getReturnType();

		// compute the size of the calling parameters
		Type[] parameters = methgen.getArgumentTypes();
		int stackIndex = methgen.isStatic() ? 0 : 1;
		for (int i = 0; i < parameters.length; i++) {
			stackIndex += parameters[i].getSize();
		}

		// save time prior to invocation
		ilist.append(ifact.createInvoke("java.lang.System",
				"currentTimeMillis", Type.LONG, Type.NO_ARGS,
				Constants.INVOKESTATIC));
		ilist.append(InstructionFactory.createStore(Type.LONG, stackIndex));

		// call the wrapped method
		int offset = 0;
		short invoke = Constants.INVOKESTATIC;
		if (!methgen.isStatic()) {
			ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0));
			offset = 1;
			invoke = Constants.INVOKEVIRTUAL;
		}
		for (int i = 0; i < parameters.length; i++) {
			Type type = parameters[i];
			ilist.append(InstructionFactory.createLoad(type, offset));
			offset += type.getSize();
		}
		ilist.append(ifact.createInvoke(cname, iname, result, parameters,
				invoke));

		// store result for return later
		if (result != Type.VOID) {
			ilist.append(InstructionFactory.createStore(result, stackIndex + 2));
		}

		// print time required for method call
		ilist.append(ifact.createFieldAccess("java.lang.System", "out",
				new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
		ilist.append(InstructionConstants.DUP);
		ilist.append(InstructionConstants.DUP);
		String text = "Call to method " + methgen.getName() + " took ";
		ilist.append(new PUSH(pgen, text));
		ilist.append(ifact.createInvoke("java.io.PrintStream", "print",
				Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
		ilist.append(ifact.createInvoke("java.lang.System",
				"currentTimeMillis", Type.LONG, Type.NO_ARGS,
				Constants.INVOKESTATIC));
		ilist.append(InstructionFactory.createLoad(Type.LONG, stackIndex));
		ilist.append(InstructionConstants.LSUB);
		ilist.append(ifact.createInvoke("java.io.PrintStream", "print",
				Type.VOID, new Type[] { Type.LONG }, Constants.INVOKEVIRTUAL));
		ilist.append(new PUSH(pgen, " ms."));
		ilist.append(ifact.createInvoke("java.io.PrintStream", "println",
				Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));

		// return result from wrapped method call
		if (result != Type.VOID) {
			ilist.append(InstructionFactory.createLoad(result, stackIndex + 2));
		}
		ilist.append(InstructionFactory.createReturn(result));

		// finalize the constructed method
		wrapgen.stripAttributes(true);
		wrapgen.setMaxStack();
		wrapgen.setMaxLocals();
		cgen.addMethod(wrapgen.getMethod());
		ilist.dispose();
	}

	public static void premain(String options, Instrumentation ins) {
		if (options != null) {
			ins.addTransformer(new Timing(options));
		} else {
			System.out
					.println("Usage: java -javaagent:Timing.jar=\"class:method\"");
			System.exit(0);
		}

	}
}


【Java基础知识 43】Java 字节码,javap命令,解读字节码清单 由于不同的操作系统和硬件架构的指令集和寄存器等硬件层次结构不同,为了实现Java程序的跨平台性,JVM需要在不同的平台上实现一套统一的指令集和操作数。Java字节码(Java bytecode)是Java语言的一种特殊格式,是Java虚拟机(JVM)能够识别和执行的一组指令。同时,由于字节码是经过编译的,因此它的执行速度可以比解释执行Java源代码更快。Java字节码是Java语言实现跨平台性的关键之一,它是Java编译器生成的中间代码,可以被JVM加载、解释和执行。65001代表编码格式为utf-8。 阅读详情

相关推荐

掌握 Java 字节码的基本操作指令(反汇编字节码)

JVM(Java虚拟机)对每个字节码指令都有特定的含义。字节码是JVM理解和执行的机器语言,JVM通过解析和执行这些字节码指令来运行Java程序。每个字节码指令都有一个操作码(opcode),操作码定义了特定的操作,以及操作所需的操作数,对应上述其中某些字节码,比如。

weixin_44711513的博客 1539

详解JAVA字节码

一文详解JAVA字节码

BugMan的博客 3381

FitzHugh-Nagumo 模型连续-MATLAB仿真

【代码】FitzHugh-Nagumo 模型连续-MATLAB仿真。

qq_43688618的博客 884

00-JAVA基础-javassist字节码操作

Javassist是一个开源的分析、编辑和创建Java字节码的类库。它是jboss的一个子项目,主要优点在于简单且快速。它允许开发者直接使用Java编码的形式,而无需了解虚拟机指令,就能动态地改变类的结构或动态生成类。Javassist提供了一组简单易用的API,使开发者能够动态地创建、修改、分析Java类,而无需关心底层的字节码细节。

丨Anna丨的博客 1750

ComfyUI破限版全中文AI绘画环境搭建与工作流实战指南

节点式工作流是AI绘画领域的核心技术架构,通过将图像生成过程拆分为可配置的模块化节点,实现了对Stable Diffusion模型的精细化控制。其技术原理基于数据流编程范式,每个节点负责特定功能处理,如文本编码、采样器配置和VAE解码等。这种设计在工程实践中的核心价值在于提供了可追溯、可复用的可视化工作流,特别适合需要参数调优和批量生产的商业场景。ComfyUI作为典型的节点式AI绘画工具,在破限版中针对中文用户优化了界面支持和显卡兼容性,显著降低了技术门槛。在实际应用中,结合ControlNet和LoRA

weixin_29038155的博客 451

CMAC算法原理

2、K1 通过以下运算导出:若 L 的最高有效位等于 0,则 K1 是 L 的左移 1 位。3、K2 通过如下运算导出:若 K1 的最高有效位等于 0,则 K2 是 K1 的左移 1 位。采用了 AES 算法中的类似 CBC 模式的加密方式,即对前一个分组的密文与当前分组的明文进行异或操作后在加密,2、分块处理:首先将消息分成多个固定长度的块,若消息长度不是块大小的倍数,则可以使用填充来将其填充到合适的大小。1、子密钥计算,通过主密钥生成子密钥(key1,key2),子密钥用于最后一个块处理;

sky的博客 1659

Java字节码介绍

Java之所以可以“一次编译,到处运行”。一是因为JVM针对各种操作系统、平台都进行了定制。二是因为无论在什么平台,都可以编译生成固定格式的字节码(.class文件)供JVM使用。因此,也可以看出字节码对于Java生态的重要性。之所以被称之为字节码,是因为字节码文件由十六进制值组成,而JVM以两个十六进制值为一组,即以字节为单位进行读取。

致力于不留技术债务cuizb.top 2747

luks-磁盘加密工具

linux磁盘加密配置工具及步骤详解

zdd56789的博客 123

java操作字节码_操作Java字节码

本博客主要介绍通过 Javassist、ASM 操作 Java 字节码。Class 文件是什么通常对于用 idea 的同学来说,class 文件是直接可以查看的,可以看到像 java 那样的代码。其实 class 文件是一种字节码文件,我们平时在 idea 所看到的,是 idea 自动反编译后的结果。如果把 class 文件用 sublime 打开,就会看到许多字节码,而不是 Java 代码了。...

weixin_39622283的博客 264

ASP.NET Core 6 Web API在IIS上的部署与调试

通过以上步骤和配置,你应该能够成功部署并调试你的ASP.NET Core 6 Web API在IIS上。记住,权限和配置是关键,确保你的环境和应用程序代码都正确设置。希望这篇博客对你部署和解决IIS上的问题有所帮助。

m0_74337424的博客 522

【网络教程】Ubuntu有线连接消失,无法联网怎么办!(亲测有效!)

文章目录问题描述解决方案 问题描述 今天打开Ubuntu,突然发现无法连接网络,并且打开设置,发现设置里面的网络已经没有了有线连接,只有VPN设置选项,如图 解决方案 按照下列的代码执行即可! # 关闭网路 service NetworkManager stop # 删除NetworkManager缓存文件 sudo rm /var/lib/NetworkManager/NetworkManager.state # 打开网络 service NetworkManager start 运行完

XiaoqiangClub的博客 1万+

BCEL与Java字节码操作

大家好,我是小黑,咱们今天来聊聊Apache Commons BCEL(Byte Code Engineering Library)。你可能会问,BCEL是什么鬼?别急,小黑这就给你娓娓道来。BCEL,它是一款专门用来操作Java字节码的库。想象一下,Java代码编译后变成了字节码,这些字节码是Java虚拟机执行的真正“源代码”。有了BCEL,咱们就能像变魔术一样,对这些字节码进行读取、修改,甚至创造出全新的字节码!那为啥要搞字节码呢?这事儿得从Java的运行原理说起。

了解➔熟悉➔掌握➔精通 1676

Unreal5从入门到精通 专栏目录

欢迎来到“UE5从入门到精通”专栏!在这里,我们将带您踏上一段精彩的旅程,深入探索虚幻引擎5(Unreal Engine 5)的无限可能。不论您是游戏开发的新手,还是希望提升技能的开发者,这里都有适合您的内容。基础知识:了解虚幻引擎5的界面、功能和基本操作,为您的学习打下坚实的基础。项目实战:通过实际项目案例,帮助您从理论走向实践,真实体验游戏开发的每个环节。高级技巧:分享各种高级功能和技巧,包括蓝图、C++编程、材质编辑、光照和渲染等,让您能够创作出更具专业水准的作品。

TxNet 2992

Java字节码操作类库汇总

Java字节码操作类库: ASMJavassistCGLIBByteBuddy

成长的足迹 1820

实战优化!C#上位机串口通信卡顿问题:超时机制+数据缓存方案

串口名</param>/// <param name="baudRate">波特率

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1065

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java基础-字节码操作

文章目录JAVA字节码操作1. 常见的字节码操作类库1.1 JAVAssist库的API详解1.2 JAVAssist库的简单实用1.3 Javassist API详解 JAVA字节码操作 Java动态性的两种常见实现方式: 字节码操作 反射 运行时操作字节码可以让我们实现如下功能: 动态生成新的类 动态改变某个类的结构(添加、删除、修改 新的属性、方法) 优势: 比反射开销...

qq_41302594的博客 403

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Apache Commons BCEL与Java字节码操作

咱们今天来聊聊Apache Commons BCEL(Byte Code Engineering Library)。你可能会问,BCEL是什么鬼?别急,小黑这就给你娓娓道来。BCEL,它是一款专门用来操作Java字节码的库。想象一下,Java代码编译后变成了字节码,这些字节码是Java虚拟机执行的真正“源代码”。有了BCEL,咱们就能像变魔术一样,对这些字节码进行读取、修改,甚至创造出全新的字节码!那为啥要搞字节码呢?这事儿得从Java的运行原理说起。

宋小黑的博客 2337

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JAVA字节码文件操作技巧

你知道如何操作JAVA字节码文件吗,这里将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,首先我们来看一下AOP的概念,AOP是OOP的延续,是AspectOrientedProgramming的缩写,意思是面向方面编程。 如何操作JAVA字节码文件 本文将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,谈到操作Java字节码,不

虚极静笃 1232

Java开源字节码操作

Javassist  Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。 更多Javassist信息   BCEL  Byte Code En

tuzi37的专栏 848

Java字节码操作

字节码操作 JAVA动态性的两种常见实现方式: 字节码操作 反射 运行时操作字节码可以实现如下功能 动态生成新的类 动态改变某个类的结构(添加/删除/修改 新的属性/方法) 优势: 比反射开销小 JAVAasist性能高于反射,低于ASM 常见的字节码操作类库 BCEL Byte Code Engineering Library(BCEL),这是Apache Softeare Foundat

张博的Blog 546

Java字节码操作之Javassist

Java的动态性两种方式实现:字节码操作和反射 运行时操作字节码可以让我们实现以下功能: 动态生成新的类 动态改变某个类的结构(添加/删除/修改 新的属性/方法) 操作字节码的优势: 比反射开销小,性能高 Javassist性能高于反射,低于ASM 而常见字节码操作类库: 此次,主要介绍Javassist相关内容: Javassist是一个开源的分析、编辑和创建Java字节码的类库,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态

ShaoDu的博客 375

java 字节码操作_Java 动态性(4) - 字节码操作

1.字节码操作JAVA动态性的两种常见实现方式字节码操作反射运行时操作字节码可以让我们实现如下功能动态生成新的类动态改变某个类的结构(添加/删除/修改 新的属性/方法)优势比反射开销小,性能高JAVAasist性能高于反射,低于asm2.常见的字节码操作类库BCELByte Code Engineering Library (BCEL), 这是Apache Software Foundation ...

weixin_33072399的博客 387

Java 动态字节码操作

运行时操作字节码可以让我们实现如下功能: 动态生成新的类 动态改变某个类的结构(添加/删除/修改 新的属性/方法) java常见的字节码操作类库 BCEL Byte Code Engineering Library (BCEL) ,这是 Apache Software Foundation 的 Jakarta 项目的一部分。 BCEL 是 Java classworking 广泛 使用的一种 框架 , 它 可以让您深入 JVM 汇编语言进行类操作的细节。 BCEL 与 Java...

追逐消失的记忆 493
上一篇: 安装subclipse, MyEclipse SVN插件
下一篇: java RMI helloworld
partner4java
博客等级 码龄17年 481粉丝 183原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值