Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting .class files #752

Open
NeumimTo opened this issue Dec 24, 2023 · 4 comments
Open

Getting .class files #752

NeumimTo opened this issue Dec 24, 2023 · 4 comments

Comments

@NeumimTo
Copy link

NeumimTo commented Dec 24, 2023

I would like to check what bytecode bsh actually generates. I found out that theres sys. property which can be used for this exact purpose - bsh.debugClasses

 public static void main(String[] a) throws Exception {
        File file = new File(".");
        System.setProperty("bsh.debugClasses", file.getAbsolutePath());

        BshScriptEngine engine = (BshScriptEngine) new BshScriptEngineFactory().getScriptEngine();

        CompiledScript compiledScript = engine.compile(script);
        Action action = (Action) compiledScript.eval();

        Interpreter interpreter = new Interpreter();
        action = (Action) interpreter.eval(script);

    }

I tried using Interpreter directly and scriptengine (which would be preferred way for me) to compile/execute bsh scripts. But none of these two approaches actually generated .class files within the dir i provided.

Im on 3.0.0 snapshot

@NeumimTo
Copy link
Author

I did some more digging. There appears to be differences between implementing an interface and inheriting from a class.

The script which i was using was just

            return new Action() {
                public int run( str ) {
                    return str.hashCode();
                }
            }

The .class file was generated only when then Action was an abstract class. No .class file was generated for case when Action was an interface.

@nickl-
Copy link
Member

nickl- commented Jan 3, 2024

This will require more in depth investigation, off hand I can say:

BeanShell only generates bytecode for virtual classes (bsh scripted classes, intefaces and enums) but uses compiled classes directly as found on the class path.

The class generation code is located in bsh.ClassGenerator which is also where the saveClasses method is which does the file persistence.

private static void saveClasses(String className, byte[] code) {
String dir = Interpreter.getSaveClassesDir();
if (dir != null) try
( FileOutputStream out = new FileOutputStream(dir + "/" + className + ".class") ) {
out.write(code);
} catch (IOException e) {
e.printStackTrace();
}
}

It may be that we are not calling this for all instances.

Hope this helps, in the interim.

@nickl-
Copy link
Member

nickl- commented Jan 3, 2024

This method is also not currently covered by unit tests, so it is very likely that you have discovered a bug where new features have not yet been included in the save class functionality.

Screenshot_20240103_122043

Your help with this will be very much appreciated.

@nickl-
Copy link
Member

nickl- commented Jan 3, 2024

The issue #72 covers some documentation which may help with writing unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants