0

I wrote a simple program that capture MIDI In events and print received message. Configuration is Windows10 + Graalvm 17 + Eclipse + standard MIDI keyboard.

The program is a simple self-content file. All works properly using JVM. MIDI out events are produced and MIDI in events are captures.

The problem appears when this program is turned into EXE. Generation is performed without any problem. MIDI out events are produced and OK But as I hit a keyboard key, the MIDI in event causes an exception.

Exception in thread "Java Sound MidiInDevice Thread" java.lang.NoSuchMethodError: com.sun.media.sound.MidiInDevice.callbackShortMessage(IJ)V
        at com.oracle.svm.jni.functions.JNIFunctions$Support.getMethodID(JNIFunctions.java:1247)
        at com.oracle.svm.jni.functions.JNIFunctions$Support.getMethodID(JNIFunctions.java:1232)
        at com.oracle.svm.jni.functions.JNIFunctions.GetMethodID(JNIFunctions.java:412)
        at com.sun.media.sound.MidiInDevice.nGetMessages(MidiInDevice.java)
        at com.sun.media.sound.MidiInDevice.run(MidiInDevice.java:127)
        at java.lang.Thread.run(Thread.java:833)
        at com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:704)
        at com.oracle.svm.core.windows.WindowsPlatformThreads.osThreadStartRoutine(WindowsPlatformThreads.java:143)

I tried to ask for initialization at 'build-time' or at 'run-time' but the problem persists. Does anyone have encountered the same issue ?

Thanks for your help.

Here after the global self-content simple code

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Transmitter;
 
public class HelloMidi {
    /** Main method. */
    public static void main(String[] args) {
        System.err.println("HelloMidi");
        //-Recover MIDI in & out
        final Receiver midiOut=pickMidiOut("ESI M4U XT");
        final Transmitter midiIn=pickMidiIn("MIDIIN4 (ESI M4U XT)");
        //-Define what to do with events recovere for keyboard
        midiIn.setReceiver(new Receiver() {
            /** {@inheritDoc} */
            @Override
            public final void send(final MidiMessage message,final long timeStamp) {
                //-A message has just been received
                System.err.print("Message received->"+message.getLength()+" bytes");
                for(final byte b:message.getMessage()) System.err.print(", "+Byte.toUnsignedInt(b));
                System.err.println();
            }
            /** {@inheritDoc} */
            @Override
            public final void close() {
                //-Nothing for this test !
            }
        });
        assert(midiOut!=null);
        try {
            midiOut.send(new ShortMessage(144,60,120),-1);
            Thread.sleep(1000);
            midiOut.send(new ShortMessage(144,67,120),-1);
            Thread.sleep(1000);
            midiOut.send(new ShortMessage(144,72,120),-1);
            Thread.sleep(20000);
            //-Print accessible devics for information
            for(final MidiDevice.Info mdi:MidiSystem.getMidiDeviceInfo()) System.err.println("Device '"+mdi.getName()+"':"+mdi);
        } catch(final Exception e) {
            //-Any problem
            e.printStackTrace();
        }
        //-Exit
        System.err.println("ByeMidi");
        System.exit(0);
    }
    /** Check for requested MIDI OUT receiver. */
    private static Receiver pickMidiOut(final String aName) {
        //-Parse all devices
        for(final MidiDevice.Info mdi:MidiSystem.getMidiDeviceInfo()) {
            //-Check name
            if(!mdi.getName().equals(aName)) continue;
            //-Try in case there are errors
            try {
                //-Recover a MIDI device
                final MidiDevice device=MidiSystem.getMidiDevice(mdi);
                //-Try to open it
                if(!device.isOpen()) device.open();
                if(!device.isOpen()) continue;
                //-Check receiver
                final Receiver answer=device.getReceiver();
                if(answer!=null) return(answer);
            } catch(final Throwable e) {
                //-Any problem
                continue;
            }
        }
        //-Return 'null' as none found
        return(null);
    }
    /** Check for requested MIDI IN transmitter. */
    private static Transmitter pickMidiIn(final String aName) {
        //-Parse all devices
        for(final MidiDevice.Info mdi:MidiSystem.getMidiDeviceInfo()) {
            //-Check name
            if(!mdi.getName().equals(aName)) continue;
            //-Try in case there are errors
            try {
                //-Recover a MIDI device
                final MidiDevice device=MidiSystem.getMidiDevice(mdi);
                //-Try to open it
                if(!device.isOpen()) device.open();
                if(!device.isOpen()) continue;
                //-Check receiver
                final Transmitter answer=device.getTransmitter();
                if(answer!=null) return(answer);
            } catch(final Throwable e) {
                //-Any problem
                continue;
            }
        }
        //-Return 'null' as none found
        return(null);
    }
}
java71
  • 1
  • 1
  • Did you provide JNI access config to `native-image`? – peterz Aug 02 '22 at 07:42
  • Hi, thanks for interresting into my problem.
    No, I did not configure anything.
    The reason is that all the MIDI out events are processed perfectly, without any specific configuration... So I expected that it was the same for MIDI IN !
    – java71 Aug 03 '22 at 20:59
  • 1
    GraalVM cannot follow JNI calls automatically, so they need to be [configured](https://www.graalvm.org/22.2/reference-manual/native-image/dynamic-features/). This also applies to reflection and resource access. From the stack trace you've posted, it seems the problem is an unconfigured Java method called up from native code. – peterz Aug 04 '22 at 06:59
  • Many thanks for the link ! I managed to include JSON information in META-INF jar and... it works !!! – java71 Aug 05 '22 at 20:05

0 Answers0