【问题标题】:Java - Memory Allocation Difficulties (GC_FOR_ALLOC)Java - 内存分配困难 (GC_FOR_ALLOC)
【发布时间】:2016-08-25 07:13:55
【问题描述】:

当我启动此线程时,我的 Android 应用程序崩溃。

这个线程应该重启手机。当我启动它时,它不会重新启动手机,并且我在 LOG 中有以下文本:

08-25 09:12:00.946 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm: GC_FOR_ALLOC 释放 1279K (30823), 55% 释放 4485K/9968K, 暂停 53ms,总共 53ms 08-25 09:12:01.294 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm: 之间 以前的 GC 分配 1280K 08-25 09:12:01.346 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm:GC_FOR_ALLOC freed 1280K (30820), 55% free 4485K/9968K, paused 52ms, total 52ms 08-25 09:12:01.713 26029-26813/com.datasulting.chris.smsgateway d/dalvikvm: 上一次GC之间的alloc 1279K 08-25 09:12:01.768 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm:GC_FOR_ALLOC freed 1279K (30813), 55% free 4486K/9968K, paused 55ms, total 55ms 08-25 09:12:02.111 26029-26813/com.datasulting.chris.smsgateway d/dalvikvm: 上一次GC alloc 1279K 08-25 09:12:02.164之间 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm:GC_FOR_ALLOC freed 1280K (30819), 55% free 4486K/9968K, paused 53ms, total 53ms 08-25 09:12:02.504 26029-26813/com.datasulting.chris.smsgateway d/dalvikvm: 上一次GC alloc 1279K 08-25 09:12:02.557之间 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm:GC_FOR_ALLOC freed 1280K (30823), 55% free 4485K/9968K, paused 53ms, total 53ms 08-25 09:12:02.901 26029-26813/com.datasulting.chris.smsgateway d/dalvikvm: 上一次GC alloc 1279K 08-25 09:12:02.956之间 26029-26813/com.datasulting.chris.smsgateway D/dalvikvm:GC_FOR_ALLOC freed 1279K (30818), 55% free 4485K/9968K, paused 55ms, total 55ms 08-25 09:12:03.298 26029-26813/com.datasulting.chris.smsgateway d/dalvikvm: 上一次GC之间alloc 1280K

这是我的主题。

class Reboot implements Runnable {

    private volatile boolean cancelled;
    Boolean checkRebootHeb;
    Boolean checkRebootQuo;
    int jourDemandeeInt;
    String jourDemandeeString;
    String weekDay;
    int dayOfWeek;
    SimpleDateFormat df;
    String heure;
    String dayOfWeekString;
    String heureDemandee;
    Calendar c;

    public Reboot(Boolean VARcheckReboot, Boolean VARcheckRebootQuo, int VARjour, String VARtextReboot) {
        checkRebootHeb = VARcheckReboot;
        checkRebootQuo = VARcheckRebootQuo;
        jourDemandeeInt = VARjour;
        heureDemandee = VARtextReboot;
    }


    @Override
    public void run() {

        while (!cancelled) {

            if (jourDemandeeInt == 0){
                jourDemandeeString = "Lundi";
            }
            if (jourDemandeeInt == 1){
                jourDemandeeString = "Mardi";
            }
            if (jourDemandeeInt == 2){
                jourDemandeeString = "Mercredi";
            }
            if (jourDemandeeInt == 3){
                jourDemandeeString = "Jeudi";
            }
            if (jourDemandeeInt == 4){
                jourDemandeeString = "Vendredi";
            }
            if (jourDemandeeInt == 5){
                jourDemandeeString = "Samedi";
            }
            if (jourDemandeeInt == 6){
                jourDemandeeString = "Dimanche";
            }

            c = Calendar.getInstance();
            dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
            df = new SimpleDateFormat("HH:mm");
            heure = df.format(c.getTime());


            if (Calendar.MONDAY == dayOfWeek) weekDay = "Lundi";
            else if (Calendar.TUESDAY == dayOfWeek) weekDay = "Mardi";
            else if (Calendar.WEDNESDAY == dayOfWeek) weekDay = "Mercredi";
            else if (Calendar.THURSDAY == dayOfWeek) weekDay = "Jeudi";
            else if (Calendar.FRIDAY == dayOfWeek) weekDay = "Vendredi";
            else if (Calendar.SATURDAY == dayOfWeek) weekDay = "Samedi";
            else if (Calendar.SUNDAY == dayOfWeek) weekDay = "Dimanche";


            dayOfWeekString = String.valueOf(dayOfWeek);

            if (checkRebootQuo == true) {
                if (heure.equals(heureDemandee)) {
                    try {

                        Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "reboot"});
                        proc.waitFor();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }

            if (checkRebootHeb == true) {
                if (dayOfWeekString.equals(jourDemandeeString)) {
                    if (heure.equals(heureDemandee)) {
                        try {

                            Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "reboot"});
                            proc.waitFor();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }

        }


    }

    public void cancel() {
        cancelled = true;
    }
}

【问题讨论】:

  • 非常感谢,对不起我的英语:p

标签: java android multithreading


【解决方案1】:

该代码有很多问题。

您的主要问题 - 您的线程正在“活动”等待。这意味着:它只是循环并创建一个新的日历对象每次迭代。然后你立即扔掉那个对象,并创建一个新对象。

您对垃圾收集器很难处理您的代码感到惊讶吗?并且只是为了确保我的讽刺不会妨碍人们理解这个问题:世界上没有任何垃圾收集器被设计为允许只创建垃圾对象的“热”循环;尤其是在“移动”世界。

所以,显而易见的答案是:在循环体中添加一些 Thread.sleep() 语句;喜欢:

  • 检查是否到了重启时间
  • 如果是:重启
  • 如果不是:睡一分钟
  • 重复

您的代码可以: - 检查是否是重新启动的时间 - 如果是:重新启动 - 重复

然后,对您(抱歉)糟糕的代码的一些一般性反馈:

  • 您将工作日转换为法语字符串以便比较它们,这绝对是疯狂的。您已经有一个 int 表示星期一为 0。然后只需将星期几的日历对象询问为 int。您正在将 0 转换为“Lundi”,以便您可以再次将 0 转换为“Lundi”以进行字符串匹配。太疯狂了。
  • 你的命名也很糟糕。真的 - 坚持使用一种语言。我猜“checkRebootQuo”是关于“每小时重启”;而“checkRebootHeb”是关于每周重新启动的。如果您将变量重命名为“rebo​​otHourly”与“rebo​​otWeekly”……那就更清楚了。
  • 最后:不要使用多个布尔参数,然后在您的方法中有多个 IF。相反:使用多态性。有知道循环和重启的基类;然后有两个子类;一个知道如何在下一小时重新启动,另一个知道如何在一周中的指定日期重新启动。

【讨论】:

  • 谢谢,但我不认为它会解决问题。这个线程有时会运行一整周。我认为这个解决方案可以解决问题,但只是暂时的。
  • 您遇到了内存问题,因为您可能每分钟创建 数百万 个对象。你一直在搅动 GC。当您添加睡眠时,您将新对象的数量减少到每分钟一个。你知道吗?
猜你喜欢
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2011-07-11
  • 2023-03-25
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多