如何确保Jython不会在编译的$py.class文件中保留“敏感”注释?

2024-06-25 06:07:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我想看看注释或字符串是否保留在$py.class文件中,所以我尝试了使用Jython 2.5.3和Jython 2.7.0进行实验。(在我的例子中,原始的.py文件不会公开,但$py.class文件是已发布的.jar的一部分;我不希望某些注释可见)

C:\tmp\jython>java -jar c:\app\java\lib\jython-standalone-2.7.0.jar
Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_152
Type "help", "copyright", "credits" or "license" for more information.
>>> import py_compile
>>> py_compile.compile('loose_lips.py')

其中loose_lips.py包含:

def loose_lips_sink_ships(x):
    """CM1 Doc comment"""

    # CM2 line comment

    """ 
    CM3 Another multiline string that doesn't do anything
    but is not a doc comment
    """

    return x+1

    """
    CM4 Yet another comment that could theoretically
    be optimized out, since we can never get here
    """

我预测CM1将是结果输出中唯一保留的字符串内容,因为它在Python中具有定义良好的语义——它是docstring,因此它被填充到loose_lips.loose_lips_sink_ships.__doc__。剩下的代码没有理由出现在任何运行时代码中

如果我在Python2.7.14中运行py_compile.compile('loose_lips.py')(或者只运行import loose_lips),那么它将生成一个包含字节码的.pyc文件,并且如预测的那样,唯一保留的文本是CM1

如果在Jython 2.5.3或Jython 2.7.0中运行py_compile.compile('loose_lips.py'),则生成的$py.class文件包含CM1和CM3

为什么CM3会在运行时保留?Jython解释器是否有任何外部可见的行为(例如保留源代码?)需要保留多行字符串?我有什么办法可以阻止它吗

我在http://www.javadecompilers.com上反编译了$py.class文件,结果如下:

import org.python.core.PyRunnableBootstrap;
import org.python.core.CodeBootstrap;
import org.python.core.CodeLoader;
import org.python.core.PyFunction;
import org.python.core.PyString;
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.ThreadState;
import org.python.core.PyFrame;
import org.python.core.PyCode;
import org.python.compiler.Filename;
import org.python.compiler.MTime;
import org.python.compiler.APIVersion;
import org.python.core.PyRunnable;
import org.python.core.PyFunctionTable;

// 
// Decompiled by Procyon v0.5.36
// 

@APIVersion(36)
@MTime(1578883953709L)
@Filename("loose_lips.py")
public class loose_lips$py extends PyFunctionTable implements PyRunnable
{
    static loose_lips$py self;
    static final PyCode f$0;
    static final PyCode loose_lips_sink_ships$1;

    public PyObject f$0(final PyFrame pyFrame, final ThreadState threadState) {
        pyFrame.setline(1);
        pyFrame.setlocal("loose_lips_sink_ships", (PyObject)new PyFunction(pyFrame.f_globals, Py.EmptyObjects, loose_lips$py.loose_lips_sink_ships$1, (PyObject)PyString.fromInterned("CM1 Doc comment")));
        pyFrame.f_lasti = -1;
        return Py.None;
    }

    public PyObject loose_lips_sink_ships$1(final PyFrame pyFrame, final ThreadState threadState) {
        pyFrame.setline(2);
        PyString.fromInterned("CM1 Doc comment");
        pyFrame.setline(9);
        PyString.fromInterned(" \n    CM3 Another multiline string that doesn't do anything\n    but is not a doc comment\n    ");
        pyFrame.setline(11);
        final PyObject add = pyFrame.getlocal(0)._add((PyObject)Py.newInteger(1));
        pyFrame.f_lasti = -1;
        return add;
    }

    public loose_lips$py(final String s) {
        loose_lips$py.self = this;
        f$0 = Py.newCode(0, new String[0], s, "<module>", 0, false, false, (PyFunctionTable)loose_lips$py.self, 0, (String[])null, (String[])null, 0, 4096);
        loose_lips_sink_ships$1 = Py.newCode(1, new String[] { "x" }, s, "loose_lips_sink_ships", 1, false, false, (PyFunctionTable)loose_lips$py.self, 1, (String[])null, (String[])null, 0, 4097);
    }

    public PyCode getMain() {
        return loose_lips$py.f$0;
    }

    public static void main(final String[] array) {
        Py.runMain(CodeLoader.createSimpleBootstrap(new loose_lips$py("loose_lips$py").getMain()), array);
    }

    public static CodeBootstrap getCodeBootstrap() {
        return PyRunnableBootstrap.getFilenameConstructorReflectionBootstrap((Class)loose_lips$py.class);
    }

    public PyObject call_function(final int n, final PyFrame pyFrame, final ThreadState threadState) {
        switch (n) {
            case 0: {
                return this.f$0(pyFrame, threadState);
            }
            case 1: {
                return this.loose_lips_sink_ships$1(pyFrame, threadState);
            }
            default: {
                return null;
            }
        }
    }
}

Tags: pyorgcoreimportstringreturnpublicfinal