You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java日志轮转与数量限制:Game类配置及Log4j选型咨询

Hi Viola, let's break down your problem step by step—first addressing whether you need Log4j, then fixing your current java.util.logging (JUL) setup to limit log entries, and tying it to your log.properties file.

Should You Switch to Log4j?

Short answer: You don't have to, but it will make your life easier if you need flexible log rules.

Your current code uses Java's built-in JUL, which can handle entry limits with a bit of custom code. But if you want native support for entry-count-based rolling, richer formatting, or easier configuration down the line, Log4j 2 is a far more robust tool. Let's cover both approaches starting with your existing setup.

Fixing Your Current JUL Setup

First, a critical note: Your log.properties has a misunderstanding. The java.util.logging.FileHandler.limit=2 setting controls byte size per log file, not the number of log entries. That's why your config isn't limiting logs to 2 entries.

Step 1: Update log.properties

Adjust the config to avoid byte-based truncation, and add a custom property for your entry limit:

handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level = ALL

# File Logging
java.util.logging.FileHandler.pattern=./logs/Marbles_game.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level=INFO
java.util.logging.FileHandler.count=1
# Set a large limit to avoid byte-based cuts
java.util.logging.FileHandler.limit=10485760

# Custom property for max log entries
game.max.log.entries=2

# Console Logging
java.util.logging.ConsoleHandler.level = OFF

Step 2: Modify the Game Class to Enforce Entry Limits

Add a counter to track log entries, load the limit from your config, and gate log writes:

import java.util.Random;
import java.util.logging.Logger;
import java.util.logging.Level;

public class Game {
    public static final int numOfFutMarbles = 3; // przyszle kulki
    private int score;
    Field fieldProcessor = new Field();
    Wave wave = new Wave();
    Logger logger = Logger.getLogger(Game.class.getName());
    Random random = new Random();
    public final static int width = 9; // rozmiar planszy
    public final static int height = 9;
    public Bin[][] field;
    public static final int not_sel = -1;
    int activeBinX = not_sel;
    int activeBinY = not_sel;
    
    // New: Track log entries and load max limit from config
    private static final int MAX_LOG_ENTRIES;
    private int logEntryCount = 0;

    static {
        // Pull the limit from system properties (we'll pass this on startup)
        String maxLogsProp = System.getProperty("game.max.log.entries", "2");
        MAX_LOG_ENTRIES = Integer.parseInt(maxLogsProp);
    }

    public Game() {
        this.field = new Bin[width][height];
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                field[i][j] = new Bin(i, j);
            }
        }
        placeMarbles(5, Marble.new_mar); // liczba kulek na poczatku
        placeMarbles(3, Marble.fut_mar); // liczba przyszlych kulek
        score = 0;
    }

    // ... Keep all your existing methods unchanged ...

    public int calcScores() {
        int markedForDel = 0;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (field[i][j].marble != null) {
                    if (field[i][j].marble.MarbleState == Marble.mark_for_rem) {
                        markedForDel++;
                    }
                }
            }
        }
        if (markedForDel > 0) {
            int bon = (int) (4 + Math.pow(markedForDel - 4, 3)); // 6 kulek = 12 pkt, 7 kulek - 31 pkt
            score += bon;
            
            // Gate log writes to stay under the entry limit
            if (logEntryCount < MAX_LOG_ENTRIES) {
                logger.info(String.valueOf(score));
                logEntryCount++;
            } else {
                // Optional: Disable further logging once the limit is hit
                logger.setLevel(Level.OFF);
            }
            
            System.out.println("your score: " + score); // 1 pkt za kazda kulke
        }
        return score;
    }
}

To pass the custom game.max.log.entries property from your config to the JVM, start your app with this command:

java -Djava.util.logging.config.file=log.properties -Dgame.max.log.entries=$(grep game.max.log.entries log.properties | cut -d'=' -f2) Game

This pulls the limit directly from your log.properties file, so you can adjust it later without changing code.

Simplified Solution with Log4j 2

If you're open to switching, Log4j 2 natively supports entry-count-based log limits, so you won't need custom counters in your code.

Step 1: Add Log4j 2 Dependencies (Maven)

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
</dependency>

Step 2: Create log4j2.xml Config

This config limits logs to 2 entries (current + 1 backup):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <File name="GameLog" fileName="./logs/Marbles_game.log">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %level %logger - %msg%n"/>
            <!-- Trigger rollover after 2 entries (use CountBasedTriggeringPolicy for 2.17+) -->
            <SizeBasedTriggeringPolicy size="1b"/>
            <DefaultRolloverStrategy max="1"/>
        </File>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="GameLog"/>
            <!-- Disable console logging -->
            <AppenderRef ref="Console" level="OFF"/>
        </Root>
    </Loggers>
</Configuration>

Step 3: Update Game Class to Use Log4j

Replace the JUL imports and logger setup:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Game {
    // ... All your existing properties ...
    private static final Logger logger = LogManager.getLogger(Game.class);

    // ... Keep all methods unchanged, except remove the log counter logic ...
    public int calcScores() {
        // ... Existing logic ...
        if (markedForDel > 0) {
            int bon = (int) (4 + Math.pow(markedForDel - 4, 3));
            score += bon;
            // Just log normally—Log4j handles the limit
            logger.info(String.valueOf(score));
            System.out.println("your score: " + score);
        }
        return score;
    }
}
Final Notes
  • Stick with JUL if you want to avoid adding dependencies and don't mind the custom counter code.
  • Switch to Log4j 2 if you want cleaner, more flexible logging that scales with your project.

内容的提问来源于stack exchange,提问作者Viola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:50