有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

从Jython调用重载Java方法的数组

当我从Jython脚本调用重载的Java方法时,我看到了一些奇怪的行为,我不明白

下面是我的Java类:

public class TestClass {
  public static float[][][] overloaded(float[][][] x) {
    return x;
  }
  public static float[][][][] overloaded(float[][][][] x) {
    return x;
  }
  public static float[][][] zeros(int n1, int n2, int n3) {
    return new float[n3][n2][n1];
  }
}

这是我的Jython脚本:

import time,TestClass
n1,n2,n3 = 250,250,250
z = TestClass.zeros(n1,n2,n3)
start = time.time()
TestClass.overloaded([z,z,z])
print 'time =',(time.time()-start)

这个Jython脚本运行大约需要1分钟,但是如果我注释掉TestClass中的第一个方法,那么脚本几乎不需要任何时间。我很困惑,当方法重载时,为什么要花这么长的时间。我错过什么了吗


共 (1) 个答案

  1. # 1 楼答案

    你的代码

    import time,TestClass
    n1,n2,n3 = 250,250,250
    z = TestClass.zeros(n1,n2,n3)
    start = time.time()
    TestClass.overloaded([z,z,z])
    print 'time =',(time.time()-start)
    

    事实

    1. Jython是基于Java的(我们已经知道了!!)
    2. 当你做n1,n2,n3 = 250,250,250并说z = TestClass.zeros(n1,n2,n3)时,基本上你是在分配250x250x250x32 bytes,即500000000 bytes477 megabytes其中32是Java中浮点的大小
    3. 当你说TestClass.overloaded([z,z,z])时,你总是要调用四维重载方法!!如果你不相信我,试试看

    我的代码运行良好

    我刚把TestClass.overloaded([z,z,z])改成了x = TestClass.overloaded([z,z,z])。而且执行速度非常快。但是在印刷时,为什么

    “为什么”部分

    它之所以失败,是因为当您执行TestClass.overloaded([z,z,z])或当我打印'x'时,python或jython需要以字符串表示形式转换对象,这就是问题所在。请参见下面的stacktrace:

    java.lang.OutOfMemoryError: Java heap space
            at java.util.Arrays.copyOfRange(Arrays.java:3209)
            at java.lang.String.<init>(String.java:215)
            at java.lang.StringBuilder.toString(StringBuilder.java:430)
            at org.python.core.PyList.list_toString(PyList.java:472)
            at org.python.core.PyList.toString(PyList.java:450)
            at org.python.core.PyArray.toString(PyArray.java:395)
            at org.python.core.PyObject.__repr__(PyObject.java:174)
            at org.python.core.PyList.list_toString(PyList.java:464)
            at org.python.core.PyList.toString(PyList.java:450)
            at org.python.core.PyArray.toString(PyArray.java:395)
            at org.python.core.PyObject.__repr__(PyObject.java:174)
    

    看。。JVM被炸了!!!!堆空间不足。。。即使你改变了JVM的内存参数,并用更多的内存来祝福这个程序,即使你所说的478 MB !!(这不仅仅是478 MB,因为你传递的是一个'z'数组,每个数组都是478 MB!!!)这就是您分配的而已,而且JVM将需要内存来保存StringBuilder字符串表示和其他一些东西

    相信我,这需要时间和大量的时间

    只是给你一些感觉

    >>> n1,n2,n3 = 2,2,2
    >>> z = TestClass.zeros(n1,n2,n3)
    >>> x = TestClass.overloaded([z,z,z])
    >>> x
    

    ^{

    array([[[F, [array([[F, [array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0
    ])]), array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0])])]), array([[F,
    [array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0])]), array([F, [array('
    f', [0.0, 0.0]), array('f', [0.0, 0.0])])]), array([[F, [array([F, [array('f', [
    0.0, 0.0]), array('f', [0.0, 0.0])]), array([F, [array('f', [0.0, 0.0]), array('
    f', [0.0, 0.0])])])])
    

    看看字符串的大小,它只是数组的2x2x2x32 bytes!!以我使用的代码为例,然后用20's更改所有的2's

    但是为什么不取消第一个方法的注释会花时间呢

    请记住,为了解决纠正重载函数的问题,jython需要计算[z,z,z],这是一个很好的内存量。这就是你看到的延迟。当您注释第一个方法时,就不会对调用产生混淆,因此它会立即返回。如果我使用你的代码,那么首先需要解析上述表达式,然后计算对象的字符串表示形式。综合起来,需要很长时间才能再次做出反应。但是,如果我使用您的代码的修改版本,即x = TestClass.overloaded([z,z,z]),那么它会变得更快,但仍然需要时间打印'x',或者可能会导致Heap Exception

    玩得开心