/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.command.system; import java.io.PrintWriter; import org.jnode.shell.AbstractCommand; import org.jnode.shell.syntax.Argument; import org.jnode.shell.syntax.EnumArgument; import org.jnode.shell.syntax.FlagArgument; import org.jnode.util.NumberUtils; import org.jnode.vm.facade.GCStatistics; import org.jnode.vm.facade.VmUtils; import org.jnode.vm.memmgr.VmHeapManager; /** * @author epr * @author crawley@jnode.org */ public class GcCommand extends AbstractCommand { private static final String help_debug_flags = "the heap debug flags"; private static final String help_set = "set these debug flags"; private static final String help_clear = "clear these debug flags"; private static final String help_show = "show the debug flags"; private static final String help_super = "Run the garbage collector"; private static final String fmt_out = "%11s: %s%n"; private static final String str_mem_size = "Memory size"; private static final String str_mem_free = "Free memory"; private static final String str_time = "Time taken"; private static final String str_stats = "Stats"; private static final String str_start = "Starting gc"; private static final String str_no_flags = "No heap debug flags set"; private static final String fmt_flags = "Heap debug flags: %s"; private enum HeapFlag { TRACE_BASIC(VmHeapManager.TRACE_BASIC), TRACE_ALLOC(VmHeapManager.TRACE_ALLOC), TRACE_TRIGGER(VmHeapManager.TRACE_TRIGGER), TRACE_OOM(VmHeapManager.TRACE_OOM), TRACE_AD_HOC(VmHeapManager.TRACE_AD_HOC), all(-1); // All flags public final int flagBit; private HeapFlag(int flagBit) { this.flagBit = flagBit; } } private class HeapDebugFlagArgument extends EnumArgument<HeapFlag> { public HeapDebugFlagArgument() { super("debugFlag", Argument.OPTIONAL | Argument.MULTIPLE, HeapFlag.class, help_debug_flags); } @Override protected String argumentKind() { return "debug flag"; } } private final HeapDebugFlagArgument argDebugFlags; private final FlagArgument argSet; private final FlagArgument argClear; private final FlagArgument argShow; public GcCommand() { super(help_super); argDebugFlags = new HeapDebugFlagArgument(); argSet = new FlagArgument("set", Argument.OPTIONAL, help_set); argClear = new FlagArgument("clear", Argument.OPTIONAL, help_clear); argShow = new FlagArgument("show", Argument.OPTIONAL, help_show); registerArguments(argDebugFlags, argClear, argSet, argShow); } public static void main(String[] args) throws Exception { new GcCommand().execute(args); } /** * Execute this command */ public void execute() throws Exception { final PrintWriter out = getOutput().getPrintWriter(); if (argSet.isSet()) { VmUtils.getVm().getHeapManager().setHeapFlags(getFlags()); } else if (argClear.isSet()) { int flags = VmUtils.getVm().getHeapManager().getHeapFlags() ^ getFlags(); VmUtils.getVm().getHeapManager().setHeapFlags(flags); } else if (argShow.isSet()) { showFlags(VmUtils.getVm().getHeapManager().getHeapFlags(), out); } else { final Runtime rt = Runtime.getRuntime(); out.format(fmt_out, str_mem_size, NumberUtils.toBinaryByte(rt.totalMemory())); out.format(fmt_out, str_mem_free, NumberUtils.toBinaryByte(rt.freeMemory())); out.println(str_start); long start = System.currentTimeMillis(); rt.gc(); GCStatistics stats = VmUtils.getVm().getHeapManager().getStatistics(); Thread.yield(); long end = System.currentTimeMillis(); out.format(fmt_out, str_mem_size, NumberUtils.toBinaryByte(rt.totalMemory())); out.format(fmt_out, str_mem_free, NumberUtils.toBinaryByte(rt.freeMemory())); out.format(fmt_out, str_time, (end - start) + "ms"); out.format(fmt_out, str_stats, stats.toString()); } } private void showFlags(int flags, PrintWriter out) { StringBuilder sb = new StringBuilder(); for (int flagBitMask = 1; flagBitMask != 0; flagBitMask = flagBitMask << 1) { if ((flags & flagBitMask) != 0) { for (HeapFlag hf : HeapFlag.values()) { if (hf.flagBit == flagBitMask) { sb.append(' ').append(hf.name()); break; } } } } if (sb.length() == 0) { out.println(str_no_flags); } else { out.format(fmt_flags, sb.toString()); } } private int getFlags() { int debugFlags = 0; if (argDebugFlags.isSet()) { for (HeapFlag flag : argDebugFlags.getValues()) { debugFlags |= flag.flagBit; } } return debugFlags; } }