You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/11/27 20:01:28 UTC

[commons-bcel] branch master updated: Unit tests and coverage for binary operations (#174)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-bcel.git


The following commit(s) were added to refs/heads/master by this push:
     new ac3c1254 Unit tests and coverage for binary operations (#174)
ac3c1254 is described below

commit ac3c1254bfab859bddb27e264d417a88ee85d8f1
Author: nbauma109 <nb...@users.noreply.github.com>
AuthorDate: Sun Nov 27 21:01:23 2022 +0100

    Unit tests and coverage for binary operations (#174)
    
    * unit tests and coverage for binary operations
    
    * Javadoc
    
    * Fix regex
    
    * Assertion on matcher.matches()
    
    * Removed "-noverify", and @DisabledForJreRange(min = JRE.JAVA_13)
    
    * Added StackMapTable attribute for BinaryOpCreator
    
    * Make StackMapType.EMPTY_ARRAY public
    
    Co-authored-by: Gary David Gregory (Code signing key) <gg...@apache.org>
---
 .../org/apache/bcel/classfile/StackMapType.java    |   2 +-
 .../org/apache/bcel/generic/BinaryOpCreator.java   | 805 +++++++++++++++++++++
 .../org/apache/bcel/util/BCELifierTestCase.java    |  60 ++
 3 files changed, 866 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/bcel/classfile/StackMapType.java b/src/main/java/org/apache/bcel/classfile/StackMapType.java
index c9d6fdc4..e43fd386 100644
--- a/src/main/java/org/apache/bcel/classfile/StackMapType.java
+++ b/src/main/java/org/apache/bcel/classfile/StackMapType.java
@@ -31,7 +31,7 @@ import org.apache.bcel.Const;
  */
 public final class StackMapType implements Cloneable {
 
-    static final StackMapType[] EMPTY_ARRAY = {};
+    public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it
 
     private byte type;
     private int index = -1; // Index to CONSTANT_Class or offset
diff --git a/src/test/java/org/apache/bcel/generic/BinaryOpCreator.java b/src/test/java/org/apache/bcel/generic/BinaryOpCreator.java
new file mode 100644
index 00000000..cd654c90
--- /dev/null
+++ b/src/test/java/org/apache/bcel/generic/BinaryOpCreator.java
@@ -0,0 +1,805 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.bcel.generic;
+
+import org.apache.bcel.Const;
+import org.apache.bcel.classfile.StackMap;
+import org.apache.bcel.classfile.StackMapEntry;
+import org.apache.bcel.classfile.StackMapType;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class BinaryOpCreator {
+
+    private static final String ORG_APACHE_BCEL_GENERIC_BINARY_OP = "org.apache.bcel.generic.BinaryOp";
+
+    private final InstructionFactory factory;
+    private final ConstantPoolGen cp;
+    private final ClassGen cg;
+
+    public BinaryOpCreator() {
+        cg = new ClassGen(ORG_APACHE_BCEL_GENERIC_BINARY_OP, "java.lang.Object", "BinaryOp.java", Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
+        cg.setMajor(Const.MAJOR_1_8);
+        cg.setMinor(Const.MINOR_1_8);
+
+        cp = cg.getConstantPool();
+        factory = new InstructionFactory(cg, cp);
+    }
+
+    public void create(final OutputStream out) throws IOException {
+        createConstructor();
+        createMethodISUB();
+        createMethodIADD();
+        createMethodIREM();
+        createMethodIMUL();
+        createMethodIDIV();
+        createMethodIAND();
+        createMethodIOR();
+        createMethodIXOR();
+        createMethodISHL();
+        createMethodISHR();
+        createMethodIUSHR();
+        createMethodLSUB();
+        createMethodLADD();
+        createMethodLREM();
+        createMethodLMUL();
+        createMethodLDIV();
+        createMethodLAND();
+        createMethodLOR();
+        createMethodLXOR();
+        createMethodLSHL();
+        createMethodLSHR();
+        createMethodLUSHR();
+        createMethodFSUB();
+        createMethodFADD();
+        createMethodFREM();
+        createMethodFMUL();
+        createMethodFDIV();
+        createMethodDSUB();
+        createMethodDADD();
+        createMethodDREM();
+        createMethodDMUL();
+        createMethodDDIV();
+        createMethodCalculate();
+        createMethodMain();
+        cg.getJavaClass().dump(out);
+    }
+
+    private void createConstructor() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.VOID, Type.NO_ARGS, new String[] {}, "<init>", ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke("java.lang.Object", "<init>", Type.VOID, Type.NO_ARGS, Const.INVOKESPECIAL));
+        il.append(InstructionFactory.createReturn(Type.VOID));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodISUB() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "isub", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("-", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIADD() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "iadd", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("+", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIREM() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "irem", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("%", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIMUL() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "imul", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("*", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIDIV() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "idiv", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("/", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIAND() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "iand", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("&", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIOR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "ior", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("|", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIXOR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "ixor", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("^", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodISHL() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "ishl", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation("<<", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodISHR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "ishr", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation(">>", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodIUSHR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.INT, new Type[] { Type.INT, Type.INT }, new String[] { "a", "b" }, "iushr", ORG_APACHE_BCEL_GENERIC_BINARY_OP,
+                il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.INT, 1));
+        il.append(InstructionFactory.createLoad(Type.INT, 2));
+        il.append(InstructionFactory.createBinaryOperation(">>>", Type.INT));
+        il.append(InstructionFactory.createReturn(Type.INT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLSUB() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lsub",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("-", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLADD() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "ladd",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("+", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLREM() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lrem",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("%", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLMUL() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lmul",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("*", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLDIV() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "ldiv",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("/", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLAND() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "land",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("&", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLOR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lor",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("|", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLXOR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lxor",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionFactory.createBinaryOperation("^", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLSHL() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lshl",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionConst.L2I);
+        il.append(InstructionFactory.createBinaryOperation("<<", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLSHR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lshr",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionConst.L2I);
+        il.append(InstructionFactory.createBinaryOperation(">>", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodLUSHR() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.LONG, new Type[] { Type.LONG, Type.LONG }, new String[] { "a", "b" }, "lushr",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.LONG, 1));
+        il.append(InstructionFactory.createLoad(Type.LONG, 3));
+        il.append(InstructionConst.L2I);
+        il.append(InstructionFactory.createBinaryOperation(">>>", Type.LONG));
+        il.append(InstructionFactory.createReturn(Type.LONG));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodFSUB() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.FLOAT, new Type[] { Type.FLOAT, Type.FLOAT }, new String[] { "a", "b" }, "fsub",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 1));
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 2));
+        il.append(InstructionFactory.createBinaryOperation("-", Type.FLOAT));
+        il.append(InstructionFactory.createReturn(Type.FLOAT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodFADD() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.FLOAT, new Type[] { Type.FLOAT, Type.FLOAT }, new String[] { "a", "b" }, "fadd",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 1));
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 2));
+        il.append(InstructionFactory.createBinaryOperation("+", Type.FLOAT));
+        il.append(InstructionFactory.createReturn(Type.FLOAT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodFREM() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.FLOAT, new Type[] { Type.FLOAT, Type.FLOAT }, new String[] { "a", "b" }, "frem",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 1));
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 2));
+        il.append(InstructionFactory.createBinaryOperation("%", Type.FLOAT));
+        il.append(InstructionFactory.createReturn(Type.FLOAT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodFMUL() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.FLOAT, new Type[] { Type.FLOAT, Type.FLOAT }, new String[] { "a", "b" }, "fmul",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 1));
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 2));
+        il.append(InstructionFactory.createBinaryOperation("*", Type.FLOAT));
+        il.append(InstructionFactory.createReturn(Type.FLOAT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodFDIV() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.FLOAT, new Type[] { Type.FLOAT, Type.FLOAT }, new String[] { "a", "b" }, "fdiv",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 1));
+        il.append(InstructionFactory.createLoad(Type.FLOAT, 2));
+        il.append(InstructionFactory.createBinaryOperation("/", Type.FLOAT));
+        il.append(InstructionFactory.createReturn(Type.FLOAT));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodDSUB() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, new String[] { "a", "b" }, "dsub",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 1));
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 3));
+        il.append(InstructionFactory.createBinaryOperation("-", Type.DOUBLE));
+        il.append(InstructionFactory.createReturn(Type.DOUBLE));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodDADD() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, new String[] { "a", "b" }, "dadd",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 1));
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 3));
+        il.append(InstructionFactory.createBinaryOperation("+", Type.DOUBLE));
+        il.append(InstructionFactory.createReturn(Type.DOUBLE));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodDREM() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, new String[] { "a", "b" }, "drem",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 1));
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 3));
+        il.append(InstructionFactory.createBinaryOperation("%", Type.DOUBLE));
+        il.append(InstructionFactory.createReturn(Type.DOUBLE));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodDMUL() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, new String[] { "a", "b" }, "dmul",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 1));
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 3));
+        il.append(InstructionFactory.createBinaryOperation("*", Type.DOUBLE));
+        il.append(InstructionFactory.createReturn(Type.DOUBLE));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodDDIV() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.DOUBLE, new Type[] { Type.DOUBLE, Type.DOUBLE }, new String[] { "a", "b" }, "ddiv",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 1));
+        il.append(InstructionFactory.createLoad(Type.DOUBLE, 3));
+        il.append(InstructionFactory.createBinaryOperation("/", Type.DOUBLE));
+        il.append(InstructionFactory.createReturn(Type.DOUBLE));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodCalculate() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.OBJECT, new Type[] { new ArrayType(Type.STRING, 1) }, new String[] { "args" }, "calculate",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+        method.addException("java.lang.Exception");
+        final StackMapType[] typesOfLocals = new StackMapType[] {new StackMapType((byte)7, cp.addClass("java.lang.String"), cp.getConstantPool()) };
+        final StackMapEntry[] table = new StackMapEntry[] {
+                new StackMapEntry(252, 70, typesOfLocals, StackMapType.EMPTY_ARRAY, cp.getConstantPool()),
+                new StackMapEntry(251, 65, StackMapType.EMPTY_ARRAY, StackMapType.EMPTY_ARRAY, cp.getConstantPool()),
+                new StackMapEntry(251, 65, StackMapType.EMPTY_ARRAY, StackMapType.EMPTY_ARRAY, cp.getConstantPool()),
+                new StackMapEntry(251, 65, StackMapType.EMPTY_ARRAY, StackMapType.EMPTY_ARRAY, cp.getConstantPool())};
+        method.addCodeAttribute(new StackMap(cp.addUtf8("StackMapTable"), 17, table, cp.getConstantPool()));
+
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionConst.AALOAD);
+        il.append(InstructionFactory.createStore(Type.OBJECT, 2));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, "i"));
+        il.append(factory.createInvoke("java.lang.String", "startsWith", Type.BOOLEAN, new Type[] { Type.STRING }, Const.INVOKEVIRTUAL));
+        final BranchInstruction ifeq1 = InstructionFactory.createBranchInstruction(Const.IFEQ, null);
+        il.append(ifeq1);
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke("java.lang.Object", "getClass", new ObjectType("java.lang.Class"), Type.NO_ARGS, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(new ObjectType("java.lang.Class"), (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(factory.createFieldAccess("java.lang.Integer", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(factory.createFieldAccess("java.lang.Integer", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"),
+                new Type[] { Type.STRING, new ArrayType(new ObjectType("java.lang.Class"), 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(Type.OBJECT, (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Integer", "parseInt", Type.INT, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new Type[] { Type.INT }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 2));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Integer", "parseInt", Type.INT, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Integer", "valueOf", new ObjectType("java.lang.Integer"), new Type[] { Type.INT }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createReturn(Type.OBJECT));
+        final InstructionHandle ih1 = il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, "l"));
+        il.append(factory.createInvoke("java.lang.String", "startsWith", Type.BOOLEAN, new Type[] { Type.STRING }, Const.INVOKEVIRTUAL));
+        final BranchInstruction ifeq2 = InstructionFactory.createBranchInstruction(Const.IFEQ, null);
+        il.append(ifeq2);
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke("java.lang.Object", "getClass", new ObjectType("java.lang.Class"), Type.NO_ARGS, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(new ObjectType("java.lang.Class"), (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(factory.createFieldAccess("java.lang.Long", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(factory.createFieldAccess("java.lang.Long", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"),
+                new Type[] { Type.STRING, new ArrayType(new ObjectType("java.lang.Class"), 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(Type.OBJECT, (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Long", "parseLong", Type.LONG, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Long", "valueOf", new ObjectType("java.lang.Long"), new Type[] { Type.LONG }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 2));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Long", "parseLong", Type.LONG, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Long", "valueOf", new ObjectType("java.lang.Long"), new Type[] { Type.LONG }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createReturn(Type.OBJECT));
+        final InstructionHandle ih2 = il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, "f"));
+        il.append(factory.createInvoke("java.lang.String", "startsWith", Type.BOOLEAN, new Type[] { Type.STRING }, Const.INVOKEVIRTUAL));
+        final BranchInstruction ifeq3 = InstructionFactory.createBranchInstruction(Const.IFEQ, null);
+        il.append(ifeq3);
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke("java.lang.Object", "getClass", new ObjectType("java.lang.Class"), Type.NO_ARGS, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(new ObjectType("java.lang.Class"), (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(factory.createFieldAccess("java.lang.Float", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(factory.createFieldAccess("java.lang.Float", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"),
+                new Type[] { Type.STRING, new ArrayType(new ObjectType("java.lang.Class"), 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(Type.OBJECT, (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Float", "parseFloat", Type.FLOAT, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Float", "valueOf", new ObjectType("java.lang.Float"), new Type[] { Type.FLOAT }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 2));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Float", "parseFloat", Type.FLOAT, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Float", "valueOf", new ObjectType("java.lang.Float"), new Type[] { Type.FLOAT }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createReturn(Type.OBJECT));
+        final InstructionHandle ih3 = il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, "d"));
+        il.append(factory.createInvoke("java.lang.String", "startsWith", Type.BOOLEAN, new Type[] { Type.STRING }, Const.INVOKEVIRTUAL));
+        final BranchInstruction ifeq4 = InstructionFactory.createBranchInstruction(Const.IFEQ, null);
+        il.append(ifeq4);
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke("java.lang.Object", "getClass", new ObjectType("java.lang.Class"), Type.NO_ARGS, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 2));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(new ObjectType("java.lang.Class"), (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(factory.createFieldAccess("java.lang.Double", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(factory.createFieldAccess("java.lang.Double", "TYPE", new ObjectType("java.lang.Class"), Const.GETSTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"),
+                new Type[] { Type.STRING, new ArrayType(new ObjectType("java.lang.Class"), 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(new PUSH(cp, 2));
+        il.append(factory.createNewArray(Type.OBJECT, (short) 1));
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 0));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Double", "parseDouble", Type.DOUBLE, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Double", "valueOf", new ObjectType("java.lang.Double"), new Type[] { Type.DOUBLE }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(InstructionConst.DUP);
+        il.append(new PUSH(cp, 1));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(new PUSH(cp, 2));
+        il.append(InstructionConst.AALOAD);
+        il.append(factory.createInvoke("java.lang.Double", "parseDouble", Type.DOUBLE, new Type[] { Type.STRING }, Const.INVOKESTATIC));
+        il.append(factory.createInvoke("java.lang.Double", "valueOf", new ObjectType("java.lang.Double"), new Type[] { Type.DOUBLE }, Const.INVOKESTATIC));
+        il.append(InstructionConst.AASTORE);
+        il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createReturn(Type.OBJECT));
+        final InstructionHandle ih4 = il.append(InstructionConst.ACONST_NULL);
+        il.append(InstructionFactory.createReturn(Type.OBJECT));
+        ifeq1.setTarget(ih1);
+        ifeq2.setTarget(ih2);
+        ifeq3.setTarget(ih3);
+        ifeq4.setTarget(ih4);
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    private void createMethodMain() {
+        final InstructionList il = new InstructionList();
+        final MethodGen method = new MethodGen(Const.ACC_PUBLIC | Const.ACC_STATIC, Type.VOID, new Type[] { new ArrayType(Type.STRING, 1) }, new String[] { "args" }, "main",
+                ORG_APACHE_BCEL_GENERIC_BINARY_OP, il, cp);
+        method.addException("java.lang.Exception");
+
+        il.append(factory.createNew(ORG_APACHE_BCEL_GENERIC_BINARY_OP));
+        il.append(InstructionConst.DUP);
+        il.append(factory.createInvoke(ORG_APACHE_BCEL_GENERIC_BINARY_OP, "<init>", Type.VOID, Type.NO_ARGS, Const.INVOKESPECIAL));
+        il.append(InstructionFactory.createStore(Type.OBJECT, 1));
+        il.append(factory.createFieldAccess("java.lang.System", "out", new ObjectType("java.io.PrintStream"), Const.GETSTATIC));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+        il.append(factory.createInvoke(ORG_APACHE_BCEL_GENERIC_BINARY_OP, "calculate", Type.OBJECT, new Type[] { new ArrayType(Type.STRING, 1) }, Const.INVOKEVIRTUAL));
+        il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.OBJECT }, Const.INVOKEVIRTUAL));
+        il.append(InstructionFactory.createReturn(Type.VOID));
+        method.setMaxStack();
+        method.setMaxLocals();
+        cg.addMethod(method.getMethod());
+        il.dispose();
+    }
+
+    public static void main(final String[] args) throws Exception {
+        final org.apache.bcel.generic.BinaryOpCreator creator = new org.apache.bcel.generic.BinaryOpCreator();
+        final Path path = Paths.get("target/test-classes/org/apache/bcel/generic/BinaryOp.class");
+        Files.deleteIfExists(path);
+        try (OutputStream out = Files.newOutputStream(path)) {
+            creator.create(out);
+        }
+    }
+}
diff --git a/src/test/java/org/apache/bcel/util/BCELifierTestCase.java b/src/test/java/org/apache/bcel/util/BCELifierTestCase.java
index 281769d7..5e5b15ff 100644
--- a/src/test/java/org/apache/bcel/util/BCELifierTestCase.java
+++ b/src/test/java/org/apache/bcel/util/BCELifierTestCase.java
@@ -18,6 +18,7 @@ package org.apache.bcel.util;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
@@ -26,11 +27,14 @@ import java.io.OutputStream;
 import java.io.PrintStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.bcel.AbstractTestCase;
 import org.apache.bcel.HelloWorldCreator;
 import org.apache.bcel.classfile.JavaClass;
 import org.apache.bcel.classfile.Utility;
+import org.apache.bcel.generic.BinaryOpCreator;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.ValueSource;
@@ -156,4 +160,60 @@ public class BCELifierTestCase extends AbstractTestCase {
         final BCELifier bcelifier = new BCELifier(javaClass, os);
         bcelifier.start();
     }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+    // @formatter:off
+        "iadd 3 2 = 5",
+        "isub 3 2 = 1",
+        "imul 3 2 = 6",
+        "idiv 3 2 = 1",
+        "irem 3 2 = 1",
+        "iand 3 2 = 2",
+        "ior 3 2 = 3",
+        "ixor 3 2 = 1",
+        "ishl 4 1 = 8",
+        "ishr 4 1 = 2",
+        "iushr 4 1 = 2",
+        "ladd 3 2 = 5",
+        "lsub 3 2 = 1",
+        "lmul 3 2 = 6",
+        "ldiv 3 2 = 1",
+        "lrem 3 2 = 1",
+        "land 3 2 = 2",
+        "lor 3 2 = 3",
+        "lxor 3 2 = 1",
+        "lshl 4 1 = 8",
+        "lshr 4 1 = 2",
+        "lushr 4 1 = 2",
+        "fadd 3 2 = 5.0",
+        "fsub 3 2 = 1.0",
+        "fmul 3 2 = 6.0",
+        "fdiv 3 2 = 1.5",
+        "frem 3 2 = 1.0",
+        "dadd 3 2 = 5.0",
+        "dsub 3 2 = 1.0",
+        "dmul 3 2 = 6.0",
+        "ddiv 3 2 = 1.5",
+        "drem 3 2 = 1.0"
+    // @formatter:on
+    })
+    public void testBinaryOp(final String exp) throws Exception {
+        BinaryOpCreator.main(new String[] {});
+        final File workDir = new File("target");
+        final Pattern pattern = Pattern.compile("([a-z]{3,5}) ([-+]?\\d*\\.?\\d+) ([-+]?\\d*\\.?\\d+) = ([-+]?\\d*\\.?\\d+)");
+        final Matcher matcher = pattern.matcher(exp);
+        assertTrue(matcher.matches());
+        final String op = matcher.group(1);
+        final String a = matcher.group(2);
+        final String b = matcher.group(3);
+        final String expected = matcher.group(4);
+        final String javaAgent = getJavaAgent();
+        if (javaAgent == null) {
+            assertEquals(expected + EOL, exec(workDir, "java", "-cp", CLASSPATH, "org.apache.bcel.generic.BinaryOp", op, a, b));
+        } else {
+            final String runtimeExecJavaAgent = javaAgent.replace("jacoco.exec", "jacoco_org.apache.bcel.generic.BinaryOp.exec");
+            assertEquals(expected + EOL, exec(workDir, "java", runtimeExecJavaAgent, "-cp", CLASSPATH, "org.apache.bcel.generic.BinaryOp", op, a, b));
+        }
+    }
 }