From 2c9ba776ec8267b8abb61482fbbebb47d83fc326 Mon Sep 17 00:00:00 2001 From: Joaquim Leitao Date: Wed, 20 May 2026 00:17:36 +0100 Subject: [PATCH 1/2] fix(lightgbm): ensuring c++ resources created in swig are released after training, even if an exception is thrown --- ...htGBMBinaryClassificationModelTrainer.java | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java b/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java index 6879406..eedc008 100644 --- a/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java +++ b/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java @@ -148,33 +148,35 @@ static void fit(final Dataset dataset, final int numIterations = parseInt(params.get(NUM_ITERATIONS_PARAMETER_NAME)); logger.debug("LightGBM model trainParams: {}", trainParams); - final SWIGTrainData swigTrainData = new SWIGTrainData( + try (SWIGTrainData swigTrainData = new SWIGTrainData( numFeatures, instancesPerChunk, FairGBMParamParserUtil.isFairnessConstrained(params), sampleWeightColIndex.isPresent() - ); - final SWIGTrainBooster swigTrainBooster = new SWIGTrainBooster(); + ); SWIGTrainBooster swigTrainBooster = new SWIGTrainBooster()) { + /// Create LightGBM dataset + final int constraintGroupColIndex = FairGBMParamParserUtil.getConstraintGroupColumnIndex(params, schema) + .orElse(FairGBMParamParserUtil.NO_SPECIFIC); + + createTrainDataset( + dataset, + numFeatures, + trainParams, + constraintGroupColIndex, + sampleWeightColIndex, + swigTrainData + ); - /// Create LightGBM dataset - final int constraintGroupColIndex = FairGBMParamParserUtil.getConstraintGroupColumnIndex(params, schema).orElse( - FairGBMParamParserUtil.NO_SPECIFIC); - createTrainDataset( - dataset, - numFeatures, - trainParams, - constraintGroupColIndex, - sampleWeightColIndex, - swigTrainData - ); + /// Create Booster from dataset + createBoosterStructure(swigTrainBooster, swigTrainData, trainParams); + trainBooster(swigTrainBooster.swigBoosterHandle, numIterations); - /// Create Booster from dataset - createBoosterStructure(swigTrainBooster, swigTrainData, trainParams); - trainBooster(swigTrainBooster.swigBoosterHandle, numIterations); + /// Save model + saveModelFileToDisk(swigTrainBooster.swigBoosterHandle, outputModelFilePath); - /// Save model - saveModelFileToDisk(swigTrainBooster.swigBoosterHandle, outputModelFilePath); - swigTrainBooster.close(); // Explicitly release C++ resources right away. They're no longer needed. + // Note: By using try-with-resources, the call to both `swigTrainData.close()` + // and `swigTrainBooster.close()` to release C++ resources is guaranteed + } } /** From dc8db8f95c8fecc844e23b684cec4b10785b242b Mon Sep 17 00:00:00 2001 From: Joaquim Leitao Date: Wed, 20 May 2026 09:41:45 +0100 Subject: [PATCH 2/2] chore(lightgbm-train): make swig variables final --- .../lightgbm/LightGBMBinaryClassificationModelTrainer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java b/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java index eedc008..4e66d08 100644 --- a/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java +++ b/openml-lightgbm/lightgbm-provider/src/main/java/com/feedzai/openml/provider/lightgbm/LightGBMBinaryClassificationModelTrainer.java @@ -148,12 +148,12 @@ static void fit(final Dataset dataset, final int numIterations = parseInt(params.get(NUM_ITERATIONS_PARAMETER_NAME)); logger.debug("LightGBM model trainParams: {}", trainParams); - try (SWIGTrainData swigTrainData = new SWIGTrainData( + try (final SWIGTrainData swigTrainData = new SWIGTrainData( numFeatures, instancesPerChunk, FairGBMParamParserUtil.isFairnessConstrained(params), sampleWeightColIndex.isPresent() - ); SWIGTrainBooster swigTrainBooster = new SWIGTrainBooster()) { + ); final SWIGTrainBooster swigTrainBooster = new SWIGTrainBooster()) { /// Create LightGBM dataset final int constraintGroupColIndex = FairGBMParamParserUtil.getConstraintGroupColumnIndex(params, schema) .orElse(FairGBMParamParserUtil.NO_SPECIFIC);