Esse recurso é comum em linguagens baseadas em máquina virtual. Permitir a execução direta de bytecode pode ser útil para implementar partes da biblioteca padrão de forma mais otimizada e com controle restrito em sandbox. A ideia é semelhante ao uso de trechos __asm__
em C para otimizações específicas e acesso a baixo nível.
Lua
Utilizando Lua, embora nao exista uma especificação de bytecode o que fica a depender da implementação/bytecode, voce consegue carregar bytecode direto em runtime.
local bytecode = '\027\076\117\097\084\000\025\147\013\010\026\010\004\008\008\120\086\000\000\000\000\000\000\000\000\000\000\000\040\119\064\001\139\064\116\101\115\116\101\046\108\117\097\129\131\000\000\002\132\011\000\000\000\131\128\000\000\068\000\002\001\071\000\001\000\130\004\134\112\114\105\110\116\004\132\111\108\097\129\000\000\000\128\132\001\000\000\001\128\128\129\133\095\069\078\086'
local func = load(bytecode)
func()
C#
Em MS Java, é perfeitamente possível codificar diretamente em assembly intermediário (IL) utilizando mnemônicos correspondentes aos opcodes. Por meio da API de Reflection.Emit, é possível construir métodos dinamicamente em tempo de execução, emitindo instruções IL manualmente.
using System;
using System.Reflection;
using System.Reflection.Emit;
class Program {
static void Main() {
var method = new DynamicMethod("Sum", typeof(int), new Type[] { typeof(int), typeof(int) });
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ret);
var sum = (Func<int, int, int>)method.CreateDelegate(typeof(Func<int, int, int>));
Console.WriteLine(sum(2, 3))
}
}
Java
Em Java, também é possível trabalhar com bytecode ou código estilo assembly, porém é necessário utilizar bibliotecas específicas para gerar ou compilar esse código antes da execução via reflexão. Diferente de linguagens que expõem diretamente suas VMs, na JVM você geralmente depende de ferramentas como ASM, Javassist ou BCEL para criar ou modificar classes dinamicamente, e então carregá-las para execução usando ClassLoader e reflexão.
import org.objectweb.asm.*;
import java.lang.reflect.Method;
public class MiniASM implements Opcodes {
public static void main(String[] args) throws Exception {
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_8, ACC_PUBLIC, "Hello", null, "java/lang/Object", null);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1,1);
mv.visitEnd();
// Método main que imprime "Olá, mundo!"
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Olá, mundo!");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(2,1);
mv.visitEnd();
cw.visitEnd();
byte[] b = cw.toByteArray();
Class<?> c = new ClassLoader() {
Class<?> define() { return defineClass("Hello", b, 0, b.length); }
}.define();
Method main = c.getMethod("main", String[].class);
main.invoke(null, (Object) new String[] {});
}
}
Outras linguagens também são possíveis nativamente, como Python e Erlang/BEAM; entre outras, também é possível estender via bibliotecas, como Ruby, Go e Wasm.