javaandroidweb3-java

Android Web3j create wallet turns out of memory and other problems with communications TLS (other similar questions did not helped me)


I have this project stopped because there is no way to solve the creating wallet step: https://github.com/EAG-es/crear_wallet_web3j Main code:

public class Create_wallet_web3j extends AppCompatActivity {
public static final int ID_REQUEST_PERMISSIONS_CODE_WRITE_STORAGE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_create_wallet);
    try {
        getWriteStoragePermission();
        if (setupBouncyCastle()) {
            create_wallet("12345", "/android.ingui.create_wallet_web3j/assets/re");
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
public boolean setupBouncyCastle() {
    final Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
    if (provider == null) {
        // Web3j will set up the provider lazily when it's first used.
        return false;
    }
    if (provider.getClass().equals(org.bouncycastle.jce.provider.BouncyCastleProvider.class)) {
        return false;
    }
    Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    org.bouncycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
//            org.spongycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider = new org.spongycastle.jce.provider.BouncyCastleProvider();
    Security.insertProviderAt(bouncyCastleProvider, 1);
    return true;
}
public File create_wallet(String password, String path) throws Exception {
    File result = null;
    File extern_dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
    File file = extern_dir;
    String [] dirs_array = path.split(File.separator);
    for (String dir: dirs_array) {
        file = new File(file, dir);
        if (file.exists() == false) {
            if (file.mkdir() == false) {
                return null;
            }
        }
    }
    if (file.exists()) {
        if (file.isDirectory()) {
            String nombre_de_archivo = WalletUtils.generateNewWalletFile(password, file);
            result = new File(file, nombre_de_archivo);
        } else {
            return null;
        }
    } else {
        return null;
    }
    return result;
}
private Boolean getWriteStoragePermission() {
    if (ActivityCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        String [] strings_array = {WRITE_EXTERNAL_STORAGE};
        requestPermissions(strings_array, ID_REQUEST_PERMISSIONS_CODE_WRITE_STORAGE);
    }
    return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    boolean is_granted = false;
    switch (requestCode) {
    case ID_REQUEST_PERMISSIONS_CODE_WRITE_STORAGE:
        if (grantResults.length > 0) {
            is_granted = true;
            for (int result: grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    is_granted = false;
                }
            }
        }
        if (is_granted == false) {
            throw new RuntimeException("Permission not Granted: " + "WRITE_EXTERNAL_STORAGE");
        }
    }
}

}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />
<application
    android:allowBackup="true"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:fullBackupContent="@xml/backup_rules"
    android:icon="@mipmap/cripto_y_mas_icono_kw"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/cripto_y_mas_icono_kw"
    android:supportsRtl="true"
    android:theme="@style/Theme.Crear_wallet_web3j"
    tools:targetApi="31">
    <activity
        android:configChanges="orientation|screenSize"
        android:name=".Create_wallet_web3j"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

gradle.build:

plugins {
id 'com.android.application'
}

android {
namespace 'android.ingui.create_wallet_web3j'
compileSdk 33

defaultConfig {
    applicationId "android.ingui.create_wallet_web3j"
    minSdk 26
    targetSdk 33
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
        options.compilerArgs += ['-Xlint:deprecation']
    }
}
}


dependencies {

implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'org.web3j:core:4.8.7-android'
//    api 'com.madgag.spongycastle:pg:1.54.0.0'
}

Using:

Android Studio Flamingo | 2022.2.1 Patch 1
Build #AI-222.4459.24.2221.9971841, built on April 19, 2023
Runtime version: 17.0.6+0-17.0.6b802.4-9586694 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Linux 5.15.0-72-generic
GC: G1 Young Generation, G1 Old Generation
Memory: 3072M
Cores: 4
Registry:
external.system.auto.import.disabled=true
ide.text.editor.with.preview.show.floating.toolbar=false
gradle.version.catalogs.dynamic.support=true
Current Desktop: XFCE

On: Linux Mint XFCE

Machine: Type: Laptop System: Hewlett-Packard product: HP ProBook 430 G1

CPU: Info: dual core model: Intel Core i5-4200U bits: 64 type: MT MCP arch: Haswell rev: 1 cache: L1: 128 KiB L2: 512 KiB L3: 3 MiB Speed (MHz): avg: 2473 high: 2570 min/max: 800/2600 cores: 1: 2534 2: 2295 3: 2494 4: 2570 bogomips: 18358

Memory: 10.99 GiB

I have tried in many ways (threads, service, Increase heap to 8 Mb,...) so I must confess I am lost...

This is the Logcat I got in my last Try (one hour to get finnished):

2023-06-22 12:20:34.479  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    W  Got a deoptimization request on un-deoptimizable method java.lang.Object java.lang.reflect.Constructor.newInstance0(java.lang.Object[])
2023-06-22 12:20:50.264  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Background young concurrent copying GC freed 44745(2472KB) AllocSpace objects, 0(0B) LOS objects, 36% free, 4380KB/6914KB, paused 34us,12us total 156.755ms
2023-06-22 12:50:27.564  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Background concurrent copying GC freed 6(16KB) AllocSpace objects, 0(0B) LOS objects, 15% free, 128MB/152MB, paused 41us,11us total 118.052ms
....
2023-06-22 13:10:10.297  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Waiting for a blocking GC Alloc
2023-06-22 13:10:10.428  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Clamp target GC heap from 215MB to 192MB
2023-06-22 13:10:10.494  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Background concurrent copying GC freed 6(144B) AllocSpace objects, 0(0B) LOS objects, 0% free, 191MB/192MB, paused 11.905ms,12us total 749.140ms
2023-06-22 13:10:10.494  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  WaitForGcToComplete blocked Alloc on Background for 197.083ms
2023-06-22 13:10:10.495  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Starting a blocking GC Alloc
2023-06-22 13:10:10.497  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Forcing collection of SoftReferences for 128KB allocation
2023-06-22 13:10:10.497  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Starting a blocking GC Alloc
2023-06-22 13:10:10.528  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Clamp target GC heap from 215MB to 192MB
2023-06-22 13:10:10.529  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Alloc concurrent copying GC freed 196(8392B) AllocSpace objects, 0(0B) LOS objects, 0% free, 191MB/192MB, paused 37us,14us total 30.848ms
2023-06-22 13:10:10.530  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    W  Throwing OutOfMemoryError "Failed to allocate a 131084 byte allocation with 17000 free bytes and 16KB until OOM, target footprint 201326592, growth limit 201326592" (VmSize 14098680 kB)
2023-06-22 13:10:10.531  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Starting a blocking GC Alloc
2023-06-22 13:10:10.532  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Starting a blocking GC Alloc
2023-06-22 13:10:10.544  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Alloc young concurrent copying GC freed 4(776B) AllocSpace objects, 0(0B) LOS objects, 0% free, 191MB/192MB, paused 55us,14us total 11.598ms
2023-06-22 13:10:10.545  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Forcing collection of SoftReferences for 128KB allocation
2023-06-22 13:10:10.545  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Starting a blocking GC Alloc
....
2023-06-22 13:10:32.127  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Background young concurrent copying GC freed 0(0B) AllocSpace objects, 0(0B) LOS objects, 0% free, 191MB/192MB, paused 30us,10us total 364.225ms
2023-06-22 13:10:32.676  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Clamp target GC heap from 215MB to 192MB
....
2023-06-22 13:10:48.330  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Background young concurrent copying GC freed 0(0B) AllocSpace objects, 0(0B) LOS objects, 0% free, 191MB/192MB, paused 55.978ms,9us total 623.327ms
2023-06-22 13:10:48.689  7769-7780  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Clamp target GC heap from 215MB to 192MB
....
2023-06-22 13:13:38.561  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  WaitForGcToComplete blocked Instrumentation on Background for 66.016ms
2023-06-22 13:19:34.870  7769-7769  AndroidRuntime          android.ingui.create_wallet_web3j    D  Shutting down VM
2023-06-22 13:19:34.904  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Waiting for a blocking GC Alloc
2023-06-22 13:19:34.939  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  WaitForGcToComplete blocked Alloc on Background for 34.873ms
2023-06-22 13:19:34.940  7769-7769  te_wallet_web3j         android.ingui.create_wallet_web3j    I  Starting a blocking GC Alloc
2023-06-22 13:19:34.966  7769-7769  AndroidRuntime          android.ingui.create_wallet_web3j    E  FATAL EXCEPTION: main
                                                                                                    Process: android.ingui.create_wallet_web3j, PID: 7769
                                                                                                    java.lang.OutOfMemoryError: Failed to allocate a 131088 byte allocation with 16800 free bytes and 16KB until OOM, target footprint 201326592, growth limit 201326592
                                                                                                        at org.bouncycastle.crypto.generators.SCrypt.SMix(Unknown Source:46)
                                                                                                        at org.bouncycastle.crypto.generators.SCrypt.MFcrypt(Unknown Source:37)
                                                                                                        at org.bouncycastle.crypto.generators.SCrypt.generate(Unknown Source:44)
                                                                                                        at org.web3j.crypto.Wallet.generateDerivedScryptKey(Wallet.java:145)
                                                                                                        at org.web3j.crypto.Wallet.create(Wallet.java:80)
                                                                                                        at org.web3j.crypto.Wallet.createStandard(Wallet.java:98)
                                                                                                        at org.web3j.crypto.WalletUtils.generateWalletFile(WalletUtils.java:81)
                                                                                                        at org.web3j.crypto.WalletUtils.generateNewWalletFile(WalletUtils.java:72)
                                                                                                        at org.web3j.crypto.WalletUtils.generateFullNewWalletFile(WalletUtils.java:50)
                                                                                                        at org.web3j.crypto.WalletUtils.generateNewWalletFile(WalletUtils.java:63)
                                                                                                        at android.ingui.create_wallet_web3j.Create_wallet_web3j.create_wallet(Create_wallet_web3j.java:65)
                                                                                                        at android.ingui.create_wallet_web3j.Create_wallet_web3j.onCreate(Create_wallet_web3j.java:29)
                                                                                                        at android.app.Activity.performCreate(Activity.java:8305)
                                                                                                        at android.app.Activity.performCreate(Activity.java:8284)
                                                                                                        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1417)
                                                                                                        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3626)
                                                                                                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3782)
                                                                                                        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
                                                                                                        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
                                                                                                        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
                                                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                        at android.os.Looper.loop(Looper.java:288)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:7872)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)


Solution

  • Finally... I still do not kwow why does not work... But I found a way to scape

    I change from WalletUtils.generateNewWalletFile to WalletUtils.generateLightNewWalletFile which returned after a very long time, with success...

    I do not know the consecuences of this change because web3j apidoc is not too good...

    I have more problems with Web3j library... Communications TLS cause trouble... After many tests, I found some librearies combinatios that worked:

    dependencies {
        ...
        implementation 'org.web3j:core:4.9.8'
        api 'com.madgag.spongycastle:pg:1.54.0.0'
    }
    

    And defining the new Provider:

        public boolean setupBouncyCastle(oks ok, Object... extras_array) throws Exception {
            if (ok.es == false) { return false; }
            try {
                final Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
                if (provider == null) {
                    return false;
                }
                if (provider.getClass().equals(org.bouncycastle.jce.provider.BouncyCastleProvider.class)) {
                    return false;
                }
                Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
    //            org.bouncycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
                org.spongycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider = new org.spongycastle.jce.provider.BouncyCastleProvider();
                Security.insertProviderAt(bouncyCastleProvider, 1);
            } catch (Exception e) {
                ok.setTxt(e);
            }
            return ok.es;
        }
    
    

    Regards