减少返回数组的方法的Java垃圾收集?

减少返回数组的方法的Java垃圾收集?,java,performance,garbage-collection,Java,Performance,Garbage Collection,对象A具有方法B(),并且在应用程序的大部分生命周期中都有效。B调用对象C方法D()。D()返回最多包含x个MyData对象的数组。MyData可能是POD(纯旧数据)/PDS(被动数据结构)或更多,但MyData可以通过调用方法或设置字段进行重用;它的特性或功能不是在建造或其他过程中铸造的 目前,B()的定义如下: class A { public B() { MyData[] amydata = c.D( 5 ); : : } } MyData[

对象A具有方法B(),并且在应用程序的大部分生命周期中都有效。B调用对象C方法D()。D()返回最多包含x个MyData对象的数组。MyData可能是POD(纯旧数据)/PDS(被动数据结构)或更多,但MyData可以通过调用方法或设置字段进行重用;它的特性或功能不是在建造或其他过程中铸造的

目前,B()的定义如下:

class A {
  public B() {
    MyData[] amydata = c.D( 5 );
       :
       :
  }
}
MyData[] D( int iRows ) {

    MyData[] amydata = new MyData[ iRows ];

    for ( int i = 0; i < iRows; i++ ) {

        if ( no more data )
            return amydata;

        amydata [ i ] = new MyData();

        // calculate or fill in MyData structure.
    }

    return amydata;
}
当前,D()的定义如下:

class A {
  public B() {
    MyData[] amydata = c.D( 5 );
       :
       :
  }
}
MyData[] D( int iRows ) {

    MyData[] amydata = new MyData[ iRows ];

    for ( int i = 0; i < iRows; i++ ) {

        if ( no more data )
            return amydata;

        amydata [ i ] = new MyData();

        // calculate or fill in MyData structure.
    }

    return amydata;
}
MyData[]D(int-iRows){
MyData[]amydata=新的MyData[iRows];
for(int i=0;i
即使数据会有所不同,A将始终或在很长一段时间内(例如,直到用户重新配置它)要求相同数量的行

那么,如果调用方在数组引用中传递:

class A {
  int iRequestSize = 5;
  int iResultSize;
  MyData[] amydata = new MyData[ iRequestSize ];

  public B() {
    iResultSize = c.D( iRequestSize, amydata );
       :
       :
    // use up to iResultSize even though array is potentially bigger.
  }
}

// returns number of rows actually used
int D( int iRowsMax, MyData[] amydata ) {

    for ( int i = 0; i < iRowsMax; i++ ) {

        if ( no more data )
            return i;

        if ( amydata [ i ] == null )
            amydata [ i ] = new MyData();

        // calculate or fill in MyData structure.
    }

    return iRowsMax;
}
A类{
int-iRequestSize=5;
国际标准尺寸;
MyData[]amydata=新的MyData[iRequestSize];
公共图书馆B(){
iResultSize=c.D(iResquestSize,数据);
:
:
//即使阵列可能更大,也最多使用iResultSize。
}
}
//返回实际使用的行数
int D(int iRowsMax,MyData[]MyData){
对于(int i=0;i

我是C++的家伙,对java来说是新的,但是假设MyDATA可以像这样循环使用,第二个版本应该避免创建和复制MyDATA,同时也要避免垃圾收集。

< P>我会说第二个变体更差。

在第一个变体中,
amydata
及其引用的所有对象都可以在方法
B()
退出时进行垃圾收集(假设B没有将对
amydata
的引用存储在其他地方)

在第二种变体中,只要
A
的实例存在,就不能对数据进行垃圾收集

考虑这样一种情况:在第一次调用
D()
时,它返回对
MyData
对象的5个引用,但在随后的调用中,它不会返回更多的行。在第一个变体中,
amydata
数组和5个引用的
MyData
对象可以在
B()
返回时立即进行垃圾收集。但是在第二种变体中,
amydata
数组和通过它引用的5
MyData
对象都不能被垃圾收集—可能永远不会在应用程序的整个运行时被垃圾收集

请记住:Java垃圾收集器针对许多短期对象进行了优化。

免责声明:阅读OP的评论,我必须承认我没有领会他的真正意图,即开发一个软实时应用程序,尽可能避免垃圾收集,这在Java世界中是非常特殊和罕见的情况

所以下面的答案与他的问题不符。但是,作为一个偶然的读者,从C++到java可能会遇到这个问题,他可能会对典型的java编程风格有一些有用的提示。
虽然java和C++的语法有很多相似之处,但是由于运行时环境非常不同,所以应该采用不同的编码风格。

作为一个几十年的Java爱好者,我当然更喜欢原始的方法签名。作为
D()
方法的调用者,我为什么要创建结果数据结构,而不是从我调用的方法获取它?这逆转了数据的自然流动

我知道,在旧C时代,动态内存管理意味着很多麻烦,在函数之外准备结果数组并让函数只填充结果是很常见的,就像编写第二个版本那样。但是忘记Java,让垃圾收集器完成它的工作(它在这方面做得非常好)。通常,试图“帮助”GC会导致实际上效率更低、更难阅读的代码。如果你真的想坚持这种风格,就不需要同时传递最大行数和数组,因为数组本身知道它的长度(这不同于老式的C数组),从而给出最大行数

你认为

第二个版本应该避免创建和复制MyData的

这听起来像是对Java内部工作的误解。每次执行
newmydata(…)
表达式时,都会在堆的某个位置创建一个新实例。提供
MyData[]
数组并不能避免这种情况。转换成C术语后,数组只包含指向
MyData
对象的指针,而不是真正的对象。Java实例很少被复制(除非您显式地调用类似于
object.clone()
)。当您为变量赋值时,它只是复制到实例的引用(=指针)

但是,如果我正确理解其目的,即使是第一个版本也远远不够完美。
D()
方法本身可以确定什么时候没有更多的可用数据,那么为什么它返回的数组要比需要的长呢?对于Java数组,这有点不方便,因此在类似的情况下,典型的Java代码返回一个
列表

关于
MyData()
构造函数和以后的“计算或填写MyData结构”的另一条注释。我知道这种风格是存在的(并且在C语言家族中非常流行),但它在Java中并不占主导地位,我尤其不喜欢它。对我来说,这听起来像是在问“给我一辆车”,然后只得到一个骨架而不是一辆可用的车。如果我想让它有轮子、引擎和座椅,我以后必须自己提供。如果有人来找我们