[SOLVED] Development on Raspberry Pi 4

Thanks for the detailed information.

I know very little about the ARM architecture. Since I don’t have an RPI of my own, I was trying to decide which cross-compiler to use.

Last night I built native libraries using the “arm-linux-gnueabi-g+±5” compiler from Ubuntu’s “g+±5-arm-linux-gnueabi” APT package, described as “GNU C++ compiler for the armel architecture”. The result is a 32-bit shared library:

sgold:~/Downloads$ file *.so
Linux_ARM32ReleaseSp_libbulletjme.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=a65fb57f30b28696d3242c9173698b122d2ba7db, not stripped

I’m hoping that’s something your JVM can load. lscpu said that your CPU’s byte order is little-endian, as suggested by the L in “armv7l”. So I think I got the byte order correct, at least.

JMonkeyEngine v3.3.2 distinguishes just 2 Linux-on-ARM platforms, denoted Linux_ARM32 and Linux_ARM64. JmeSystemDelegate identifies Linux-on-ARM based on Java’s “os.name” property and distinguishes the wordsize (32 or 64 bits) based on Java’s “os.arch” property.

The values of those 2 properties may prove important. To find them out:

public class Main {
    public static void main(String[] args) {
        System.out.println("os.name = " + System.getProperty("os.name"));
        System.out.println("is.arch = " + System.getProperty("os.arch"));
    }
}

Thinking “out loud” here … if JmeDesktopSystem finds “com.jme3.bullet.util.NativeMeshUtil” in the classpath, it will try to load a native physics library. If it believes the platform is Linux_ARM32, it will extract the native physics library from “native/linux/arm32/libbulletjme.so” in the classpath. So that’s where the new native library must go.

1 Like

Mmmm, last time I did the os.name and os.arch I got: os.name returns “Linux” and os.arch returns “arm”. so it doesn’t say 32 or 64. But it could have changed since last time I tried it.

1 Like

Due to these annotations , JmeSystemDelegate already knows that the RaspiOS is an arm32 & it’s true

1 Like

you are correct, it detects it as 32 bits.

1 Like

That’s true , I have tried that as well

Interesting command , why i didnot try that before :sweat_smile:
All you need to know about java RPI4B

pi@raspberrypi:~ $ java -XshowSettings:all
VM settings:
    Max. Heap Size (Estimated): 468.00M
    Using VM: OpenJDK Server VM

Property settings:
    awt.toolkit = sun.awt.X11.XToolkit
    file.encoding = UTF-8
    file.separator = /
    java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
    java.awt.printerjob = sun.print.PSPrinterJob
    java.class.path = 
    java.class.version = 55.0
    java.home = /usr/lib/jvm/java-11-openjdk-armhf
    java.io.tmpdir = /tmp
    java.library.path = /usr/java/packages/lib
        /usr/lib/arm-linux-gnueabihf/jni
        /lib/arm-linux-gnueabihf
        /usr/lib/arm-linux-gnueabihf
        /usr/lib/jni
        /lib
        /usr/lib
    java.runtime.name = OpenJDK Runtime Environment
    java.runtime.version = 11.0.9+11-post-Raspbian-1deb10u1
    java.specification.name = Java Platform API Specification
    java.specification.vendor = Oracle Corporation
    java.specification.version = 11
    java.vendor = Raspbian
    java.vendor.url = Unknown
    java.vendor.url.bug = Unknown
    java.version = 11.0.9
    java.version.date = 2020-10-20
    java.vm.info = mixed mode
    java.vm.name = OpenJDK Server VM
    java.vm.specification.name = Java Virtual Machine Specification
    java.vm.specification.vendor = Oracle Corporation
    java.vm.specification.version = 11
    java.vm.vendor = Raspbian
    java.vm.version = 11.0.9+11-post-Raspbian-1deb10u1
    jdk.debug = release
    line.separator = \n 
    os.arch = arm
    os.name = Linux
    os.version = 5.4.79-v7l+
    path.separator = :
    sun.arch.abi = 
    sun.arch.data.model = 32
    sun.boot.library.path = /usr/lib/jvm/java-11-openjdk-armhf/lib
    sun.cpu.endian = little
    sun.cpu.isalist = 
    sun.io.unicode.encoding = UnicodeLittle
    sun.java.launcher = SUN_STANDARD
    sun.jnu.encoding = UTF-8
    sun.management.compiler = HotSpot Tiered Compilers
    sun.os.patch.level = unknown
    user.country = US
    user.dir = /home/pi
    user.home = /home/pi
    user.language = en
    user.name = pi
    user.timezone = 

Locale settings:
    default locale = English (United States)
    default display locale = English (United States)
    default format locale = English (United States)
    available locales = , af, af_NA, af_ZA, agq, agq_CM, ak, ak_GH, 
        am, am_ET, ar, ar_001, ar_AE, ar_BH, ar_DJ, ar_DZ, 
        ar_EG, ar_EH, ar_ER, ar_IL, ar_IQ, ar_JO, ar_KM, ar_KW, 
        ar_LB, ar_LY, ar_MA, ar_MR, ar_OM, ar_PS, ar_QA, ar_SA, 
        ar_SD, ar_SO, ar_SS, ar_SY, ar_TD, ar_TN, ar_YE, as, 
        as_IN, asa, asa_TZ, ast, ast_ES, az, az_AZ_#Cyrl, az_AZ_#Latn, 
        az__#Cyrl, az__#Latn, bas, bas_CM, be, be_BY, bem, bem_ZM, 
        bez, bez_TZ, bg, bg_BG, bm, bm_ML, bn, bn_BD, 
        bn_IN, bo, bo_CN, bo_IN, br, br_FR, brx, brx_IN, 
        bs, bs_BA_#Cyrl, bs_BA_#Latn, bs__#Cyrl, bs__#Latn, ca, ca_AD, ca_ES, 
        ca_ES_VALENCIA, ca_FR, ca_IT, ccp, ccp_BD, ccp_IN, ce, ce_RU, 
        cgg, cgg_UG, chr, chr_US, ckb, ckb_IQ, ckb_IR, cs, 
        cs_CZ, cu, cu_RU, cy, cy_GB, da, da_DK, da_GL, 
        dav, dav_KE, de, de_AT, de_BE, de_CH, de_DE, de_IT, 
        de_LI, de_LU, dje, dje_NE, dsb, dsb_DE, dua, dua_CM, 
        dyo, dyo_SN, dz, dz_BT, ebu, ebu_KE, ee, ee_GH, 
        ee_TG, el, el_CY, el_GR, en, en_001, en_150, en_AG, 
        en_AI, en_AS, en_AT, en_AU, en_BB, en_BE, en_BI, en_BM, 
        en_BS, en_BW, en_BZ, en_CA, en_CC, en_CH, en_CK, en_CM, 
        en_CX, en_CY, en_DE, en_DG, en_DK, en_DM, en_ER, en_FI, 
        en_FJ, en_FK, en_FM, en_GB, en_GD, en_GG, en_GH, en_GI, 
        en_GM, en_GU, en_GY, en_HK, en_IE, en_IL, en_IM, en_IN, 
        en_IO, en_JE, en_JM, en_KE, en_KI, en_KN, en_KY, en_LC, 
        en_LR, en_LS, en_MG, en_MH, en_MO, en_MP, en_MS, en_MT, 
        en_MU, en_MW, en_MY, en_NA, en_NF, en_NG, en_NL, en_NR, 
        en_NU, en_NZ, en_PG, en_PH, en_PK, en_PN, en_PR, en_PW, 
        en_RW, en_SB, en_SC, en_SD, en_SE, en_SG, en_SH, en_SI, 
        en_SL, en_SS, en_SX, en_SZ, en_TC, en_TK, en_TO, en_TT, 
        en_TV, en_TZ, en_UG, en_UM, en_US, en_US_POSIX, en_VC, en_VG, 
        en_VI, en_VU, en_WS, en_ZA, en_ZM, en_ZW, eo, eo_001, 
        es, es_419, es_AR, es_BO, es_BR, es_BZ, es_CL, es_CO, 
        es_CR, es_CU, es_DO, es_EA, es_EC, es_ES, es_GQ, es_GT, 
        es_HN, es_IC, es_MX, es_NI, es_PA, es_PE, es_PH, es_PR, 
        es_PY, es_SV, es_US, es_UY, es_VE, et, et_EE, eu, 
        eu_ES, ewo, ewo_CM, fa, fa_AF, fa_IR, ff, ff_CM, 
        ff_GN, ff_MR, ff_SN, fi, fi_FI, fil, fil_PH, fo, 
        fo_DK, fo_FO, fr, fr_BE, fr_BF, fr_BI, fr_BJ, fr_BL, 
        fr_CA, fr_CD, fr_CF, fr_CG, fr_CH, fr_CI, fr_CM, fr_DJ, 
        fr_DZ, fr_FR, fr_GA, fr_GF, fr_GN, fr_GP, fr_GQ, fr_HT, 
        fr_KM, fr_LU, fr_MA, fr_MC, fr_MF, fr_MG, fr_ML, fr_MQ, 
        fr_MR, fr_MU, fr_NC, fr_NE, fr_PF, fr_PM, fr_RE, fr_RW, 
        fr_SC, fr_SN, fr_SY, fr_TD, fr_TG, fr_TN, fr_VU, fr_WF, 
        fr_YT, fur, fur_IT, fy, fy_NL, ga, ga_IE, gd, 
        gd_GB, gl, gl_ES, gsw, gsw_CH, gsw_FR, gsw_LI, gu, 
        gu_IN, guz, guz_KE, gv, gv_IM, ha, ha_GH, ha_NE, 
        ha_NG, haw, haw_US, hi, hi_IN, hr, hr_BA, hr_HR, 
        hsb, hsb_DE, hu, hu_HU, hy, hy_AM, ig, ig_NG, 
        ii, ii_CN, in, in_ID, is, is_IS, it, it_CH, 
        it_IT, it_SM, it_VA, iw, iw_IL, ja, ja_JP, ja_JP_JP_#u-ca-japanese, 
        jgo, jgo_CM, ji, ji_001, jmc, jmc_TZ, ka, ka_GE, 
        kab, kab_DZ, kam, kam_KE, kde, kde_TZ, kea, kea_CV, 
        khq, khq_ML, ki, ki_KE, kk, kk_KZ, kkj, kkj_CM, 
        kl, kl_GL, kln, kln_KE, km, km_KH, kn, kn_IN, 
        ko, ko_KP, ko_KR, kok, kok_IN, ks, ks_IN, ksb, 
        ksb_TZ, ksf, ksf_CM, ksh, ksh_DE, kw, kw_GB, ky, 
        ky_KG, lag, lag_TZ, lb, lb_LU, lg, lg_UG, lkt, 
        lkt_US, ln, ln_AO, ln_CD, ln_CF, ln_CG, lo, lo_LA, 
        lrc, lrc_IQ, lrc_IR, lt, lt_LT, lu, lu_CD, luo, 
        luo_KE, luy, luy_KE, lv, lv_LV, mas, mas_KE, mas_TZ, 
        mer, mer_KE, mfe, mfe_MU, mg, mg_MG, mgh, mgh_MZ, 
        mgo, mgo_CM, mk, mk_MK, ml, ml_IN, mn, mn_MN, 
        mr, mr_IN, ms, ms_BN, ms_MY, ms_SG, mt, mt_MT, 
        mua, mua_CM, my, my_MM, mzn, mzn_IR, naq, naq_NA, 
        nb, nb_NO, nb_SJ, nd, nd_ZW, nds, nds_DE, nds_NL, 
        ne, ne_IN, ne_NP, nl, nl_AW, nl_BE, nl_BQ, nl_CW, 
        nl_NL, nl_SR, nl_SX, nmg, nmg_CM, nn, nn_NO, nnh, 
        nnh_CM, no, no_NO, no_NO_NY, nus, nus_SS, nyn, nyn_UG, 
        om, om_ET, om_KE, or, or_IN, os, os_GE, os_RU, 
        pa, pa_IN_#Guru, pa_PK_#Arab, pa__#Arab, pa__#Guru, pl, pl_PL, prg, 
        prg_001, ps, ps_AF, pt, pt_AO, pt_BR, pt_CH, pt_CV, 
        pt_GQ, pt_GW, pt_LU, pt_MO, pt_MZ, pt_PT, pt_ST, pt_TL, 
        qu, qu_BO, qu_EC, qu_PE, rm, rm_CH, rn, rn_BI, 
        ro, ro_MD, ro_RO, rof, rof_TZ, ru, ru_BY, ru_KG, 
        ru_KZ, ru_MD, ru_RU, ru_UA, rw, rw_RW, rwk, rwk_TZ, 
        sah, sah_RU, saq, saq_KE, sbp, sbp_TZ, sd, sd_PK, 
        se, se_FI, se_NO, se_SE, seh, seh_MZ, ses, ses_ML, 
        sg, sg_CF, shi, shi_MA_#Latn, shi_MA_#Tfng, shi__#Latn, shi__#Tfng, si, 
        si_LK, sk, sk_SK, sl, sl_SI, smn, smn_FI, sn, 
        sn_ZW, so, so_DJ, so_ET, so_KE, so_SO, sq, sq_AL, 
        sq_MK, sq_XK, sr, sr_BA, sr_BA_#Cyrl, sr_BA_#Latn, sr_CS, sr_ME, 
        sr_ME_#Cyrl, sr_ME_#Latn, sr_RS, sr_RS_#Cyrl, sr_RS_#Latn, sr_XK_#Cyrl, sr_XK_#Latn, sr__#Cyrl, 
        sr__#Latn, sv, sv_AX, sv_FI, sv_SE, sw, sw_CD, sw_KE, 
        sw_TZ, sw_UG, ta, ta_IN, ta_LK, ta_MY, ta_SG, te, 
        te_IN, teo, teo_KE, teo_UG, tg, tg_TJ, th, th_TH, 
        th_TH_TH_#u-nu-thai, ti, ti_ER, ti_ET, tk, tk_TM, to, to_TO, 
        tr, tr_CY, tr_TR, tt, tt_RU, twq, twq_NE, tzm, 
        tzm_MA, ug, ug_CN, uk, uk_UA, ur, ur_IN, ur_PK, 
        uz, uz_AF_#Arab, uz_UZ_#Cyrl, uz_UZ_#Latn, uz__#Arab, uz__#Cyrl, uz__#Latn, vai, 
        vai_LR_#Latn, vai_LR_#Vaii, vai__#Latn, vai__#Vaii, vi, vi_VN, vo, vo_001, 
        vun, vun_TZ, wae, wae_CH, wo, wo_SN, xog, xog_UG, 
        yav, yav_CM, yo, yo_BJ, yo_NG, yue, yue_CN_#Hans, yue_HK_#Hant, 
        yue__#Hans, yue__#Hant, zgh, zgh_MA, zh, zh_CN, zh_CN_#Hans, zh_HK, 
        zh_HK_#Hans, zh_HK_#Hant, zh_MO_#Hans, zh_MO_#Hant, zh_SG, zh_SG_#Hans, zh_TW, zh_TW_#Hant, 
        zh__#Hans, zh__#Hant, zu, zu_ZA
Operating System Metrics:
    Provider: cgroupv1
    Effective CPU Count: 4
    CPU Period: 100000us
    CPU Quota: -1
    CPU Shares: -1
    List of Processors, 4 total: 
    0 1 2 3 
    List of Effective Processors, 4 total: 
    0 1 2 3 
    List of Memory Nodes, 1 total: 
    0 
    List of Available Memory Nodes, 1 total: 
    0 
    CPUSet Memory Pressure Enabled: false
    Memory Limit: 0.00K
    Memory Soft Limit: 0.00K
    Memory & Swap Limit: 0.00K
    Kernel Memory Limit: 0.00K
    TCP Memory Limit: 0.00K
    Out Of Memory Killer Enabled: true

Usage: java [options] <mainclass> [args...]
           (to execute a class)
   or  java [options] -jar <jarfile> [args...]
           (to execute a jar file)
   or  java [options] -m <module>[/<mainclass>] [args...]
       java [options] --module <module>[/<mainclass>] [args...]
           (to execute the main class in a module)
   or  java [options] <sourcefile> [args]
           (to execute a single source-file program)

 Arguments following the main class, source file, -jar <jarfile>,
 -m or --module <module>/<mainclass> are passed as the arguments to
 main class.

 where options include:

    -zero	  to select the "zero" VM
    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
    --class-path <class search path of directories and zip/jar files>
                  A : separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
    -p <module path>
    --module-path <module path>...
                  A : separated list of directories, each directory
                  is a directory of modules.
    --upgrade-module-path <module path>...
                  A : separated list of directories, each directory
                  is a directory of modules that replace upgradeable
                  modules in the runtime image
    --add-modules <module name>[,<module name>...]
                  root modules to resolve in addition to the initial module.
                  <module name> can also be ALL-DEFAULT, ALL-SYSTEM,
                  ALL-MODULE-PATH.
    --list-modules
                  list observable modules and exit
    -d <module name>
    --describe-module <module name>
                  describe a module and exit
    --dry-run     create VM and load main class but do not execute main method.
                  The --dry-run option may be useful for validating the
                  command-line options such as the module system configuration.
    --validate-modules
                  validate all modules and exit
                  The --validate-modules option may be useful for finding
                  conflicts and other errors with modules on the module path.
    -D<name>=<value>
                  set a system property
    -verbose:[class|module|gc|jni]
                  enable verbose output
    -version      print product version to the error stream and exit
    --version     print product version to the output stream and exit
    -showversion  print product version to the error stream and continue
    --show-version
                  print product version to the output stream and continue
    --show-module-resolution
                  show module resolution output during startup
    -? -h -help
                  print this help message to the error stream
    --help        print this help message to the output stream
    -X            print help on extra options to the error stream
    --help-extra  print help on extra options to the output stream
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions with specified granularity
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions with specified granularity
    -esa | -enablesystemassertions
                  enable system assertions
    -dsa | -disablesystemassertions
                  disable system assertions
    -agentlib:<libname>[=<options>]
                  load native agent library <libname>, e.g. -agentlib:jdwp
                  see also -agentlib:jdwp=help
    -agentpath:<pathname>[=<options>]
                  load native agent library by full pathname
    -javaagent:<jarpath>[=<options>]
                  load Java programming language agent, see java.lang.instrument
    -splash:<imagepath>
                  show splash screen with specified image
                  HiDPI scaled images are automatically supported and used
                  if available. The unscaled image filename, e.g. image.ext,
                  should always be passed as the argument to the -splash option.
                  The most appropriate scaled image provided will be picked up
                  automatically.
                  See the SplashScreen API documentation for more information
    @argument files
                  one or more argument files containing options
    -disable-@files
                  prevent further argument file expansion
    --enable-preview
                  allow classes to depend on preview features of this release
To specify an argument for a long option, you can use --<name>=<value> or
--<name> <value>.
2 Likes

o_O …this is my new favorite thing.

If I had a dollar for every time I’ve made code to do this…

3 Likes

I think you are now very specifically sure about what you are dealing with :slightly_smiling_face:

What type of binary is your JVM? My desktop system, for instance has “ELF 64-bit LSB shared object, x86-64, version 1”:

sgold:~$ file /usr/lib/jvm/java-11-openjdk-amd64/bin/java
/usr/lib/jvm/java-11-openjdk-amd64/bin/java: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7052e2b972e6a08b91aa436865d9df9378347a29, for GNU/Linux 3.2.0, stripped

I’m hoping your RPI has something like “ELF 32-bit LSB shared object, ARM, EABI5 version 1”.

1 Like

Sorry , I cannot understand you correctly , is it what you are searching for ?

1 Like

At the Linux command line, please type file /usr/lib/jvm/java-11-openjdk-armhf/bin/java and report the output.

1 Like

All in one command:

readlink -f `which java` | xargs file

(note back ticks instead of single quotes.)

I guess this is easier to read for those unfamiliar with back ticking:

which java | xargs readlink -f | xargs file
1 Like

@Pavl_G: The new version of Minie (with Linux_ARM32 support) is ready for testing:

    implementation 'com.github.stephengold:Minie:3.1.0-test3'

A cautious starting point would be to see whether JME can load it:

import com.jme3.system.NativeLibraryLoader;

public class Main {
    public static void main(String[] arguments) {
        NativeLibraryLoader.loadNativeLibrary("bulletjme", true);
        System.out.println("Success!");
    }
}
1 Like
pi@raspberrypi:~ $ file /usr/lib/jvm/java-11-openjdk-armhf/bin/java
/usr/lib/jvm/java-11-openjdk-armhf/bin/java: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=587a2b515eff472317d2cdf2673956695b1bb2d9, stripped```
1 Like

Thanks.

It says “executable” instead of “shared object”. I think that just means it’s a statically linked binary. So that’s fine.

I believe you’re ready to start testing.

1 Like

That was the first test , but it seems that jme can locate the file but cannot open it ,

Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/pi/IdeaProjects/RPI4B/libbulletjme.so: /home/pi/IdeaProjects/RPI4B/libbulletjme.so: cannot open shared object file: No such file or directory
	at java.base/java.lang.ClassLoader$NativeLibrary.load0(Native Method)
	at java.base/java.lang.ClassLoader$NativeLibrary.load(ClassLoader.java:2442)
	at java.base/java.lang.ClassLoader$NativeLibrary.loadLibrary(ClassLoader.java:2498)
	at java.base/java.lang.ClassLoader.loadLibrary0(ClassLoader.java:2694)
	at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2627)
	at java.base/java.lang.Runtime.load0(Runtime.java:768)
	at java.base/java.lang.System.load(System.java:1837)
	at com.jme3.system.NativeLibraryLoader.loadNativeLibrary(NativeLibraryLoader.java:685)
	at JmETest.main(JmETest.java:11)

Does this mean that the gradle have loaded it locally,but jme cannot locate it ?

1 Like

At runtime, JMonkeyEngine is supposed to extract the “libbulletjme.so” asset from the classpath to a file and then load that file. Usually the extracted file goes in the working directory.

Is “/home/pi/IdeaProjects/RPI4B” the directory where you’re running the test app?

PS: If the working directory already has a “libbulletjme.so” (perhaps for a different platform) that might cause problems. Try deleting the existing “libbulletjme.so” before re-running the test.

1 Like

Yes , & you can see it from the image attached

Tried it now but not working , also I have checked my Gradle dependencies for any incompatible libraries but cannot find any .

1 Like

Thank you. And what type of binary is that “libbulletjme.so”?

file /home/pi/IdeaProjects/RPI4B/libbulletjme.so
1 Like