5

最近,我在 Scala 中编写了一些 Android 应用程序,使用 Eclipse。一切都很好,直到我的程序只有几个课程/活动。当我添加更多代码时,JVM 开始崩溃,eclipse 经常冻结,adb 不断失去连接。任务管理器显示 Java 进程占用了 800 到 1300 MB 内存!

我的电脑的硬件参数非常好,比如 i7 3rd gen、8GB DDR3 和 SSD 256。所以这不是原因。

我的软件也是最新的,包含最新版本的 Eclipse、Android SDK、Scala 和 Java 开发工具包,所有 Eclipse 插件。-vmargs 是为 Scala 开发配置的,但它根本没有帮助。所以我把它作为问题的原因消除了。

当我将我的代码重写为 Java 时,一切都很顺利,我可以继续我的项目。

有没有人已经找到了一些在 Android 项目中使用 scala 的解决方案?我在这里和谷歌群组上阅读了几个类似的主题,但没有关于这个问题的答案。

编辑:

我用可视化 vm 分析了我的代码,但堆空间的使用是正常的。这是我的代码的一些片段。

imports ...

class MainActivity extends FragmentActivity {
  private lazy val timePicker = findViewById(R.id.timePicker).asInstanceOf[TimePicker]
  private lazy val spinner_sourceBank = findViewById(R.id.spinnerSource).asInstanceOf[Spinner]
  private lazy val spinner_targetBank = findViewById(R.id.spinnerDestination).asInstanceOf[Spinner]
  private lazy val myApplication = getApplication.asInstanceOf[MyApplication]
  private var ignoreTimeChange = false

  override protected def onCreate(savedInstanceState: Bundle) = {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    timePicker.setIs24HourView(true)
    initializeSpinner(spinner_sourceBank)
    initializeSpinner(spinner_targetBank)
  }

  private def initializeSpinner(spinner: Spinner) = {
    val adapter = ArrayAdapter.createFromResource(this, R.array.banks, R.layout.spinner_item)
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    spinner.setAdapter(adapter)
  }

  def reset(w: View) = {
    timePicker.setCurrentHour(13)
    timePicker.setCurrentMinute(00)
    spinner_sourceBank.setSelection(0)
    spinner_targetBank.setSelection(0)
  }

  def submit(w: View) = {
    if (spinner_sourceBank.getSelectedItemPosition == 0 || spinner_targetBank.getSelectedItemPosition == 0) {
      new AlertDialog.Builder(this).setPositiveButton("OK", new OnClickListener {
        override def onClick(dialog: DialogInterface, which: Int) { dialog dismiss }
      }).setMessage(getString(R.string.alert_title)).setTitle("Alert Dialog").setIcon(android.R.drawable.ic_dialog_alert).create.show
    } else manageFragments(sourceBank, targetBank)
  }

  def manageFragments(sourceBank: String, targetBank: String) = {
    val fragmentTransaction = getSupportFragmentManager.beginTransaction

    if (targetBank == sourceBank) myApplication.setCurrentFragment(MyApplication.NOW)
    else myApplication.setCurrentFragment(MyApplication.FIRST_SESSION)

    fragmentTransaction.replace(R.id.fragment_container, myApplication.getCurrentFragment)
    fragmentTransaction.commit
  }

  override def onCreateOptionsMenu(menu: Menu): Boolean = { getMenuInflater.inflate(R.menu.activity_main, menu); true }
}

我可以在移动设备上测试我的应用程序,它运行得很好。我也可以编写我的代码,但是 eclipse 的行为就像在旧计算机上运行一样——切换选项卡需要很多时间,因此构建和部署。

4

2 回答 2

5

将这些添加到 eclipse.ini(或编辑,如果存在),因为它们更适合 Scala 开发:它们应该出现在 eclipse 条目下方,例如 -vm:

-Xverify:none
-Dosgi.requiredJavaVersion=1.6
-Xms900m
-Xmx900m
-Xss2m
-XX:PermSize=256m
-XX:MaxPermSize=256m
-XX:MaxGCPauseMillis=20
-XX:MaxHeapFreeRatio=70
-XX:+ScavengeBeforeFullGC
-XX:+UseParallelOldGC
-XX:+UnlockExperimentalVMOptions
-XX:+UseFastAccessorMethods
-XX:ReservedCodeCacheSize=128m
-XX:+TieredCompilation
-XX:+AggressiveOpts

可能不太可能,但如果您使用的是 CMS GC,请从文件中删除对它的引用。

于 2013-01-05T21:01:01.000 回答
-1

虽然我没有在 Android 特定的开发中做到这一点,但我在学习“Scala 中的函数编程原理”Coursera 课程时遇到了类似的问题。结果是 Eclipse JVM 的 PermGen 空间已经达到极限,这导致了各种随机和混乱的 Eclipse 行为。事实证明,在幕后,Scala 编译器生成的类文件数量是大致相同大小的 Java 项目的许多倍。因此,我在 Eclipse 的命令行启动中添加了以下内容:

-XX:MaxPermSize=256m

在此之前,我遇到了最奇怪的 Eclipse 错误,在最奇怪的时候,我没有合理的方法来始终如一地重现它们。我在课程的前三周就有了这个。我几乎退出了这门课程,因为我使用的是我为课程明确下载的 TypeSafe 版本的 Eclipse。一旦我将上述内容添加到 Eclipse 的 JVM 启动中,我就没有其他问题了。我无法相信 Scala IDE 有多棒,因为在此之前我从未能够稳定地使用它。

希望这可以帮助。

于 2013-01-05T18:57:34.710 回答