Skip to content

Commit 3660551

Browse files
DSheirerDennis Sheirer
andauthored
#1498 Updates JMBE audio module to retain class reference instead of reflectively loading the class each time for a new instance. Reduces pressure on both the class loader and the garbage collector. (#1499)
Co-authored-by: Dennis Sheirer <[email protected]>
1 parent 39ebdb4 commit 3660551

File tree

1 file changed

+74
-79
lines changed

1 file changed

+74
-79
lines changed

src/main/java/io/github/dsheirer/audio/codec/mbe/JmbeAudioModule.java

Lines changed: 74 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
/*
2+
* *****************************************************************************
3+
* Copyright (C) 2014-2023 Dennis Sheirer
24
*
3-
* * ******************************************************************************
4-
* * Copyright (C) 2014-2019 Dennis Sheirer
5-
* *
6-
* * This program is free software: you can redistribute it and/or modify
7-
* * it under the terms of the GNU General Public License as published by
8-
* * the Free Software Foundation, either version 3 of the License, or
9-
* * (at your option) any later version.
10-
* *
11-
* * This program is distributed in the hope that it will be useful,
12-
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
13-
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14-
* * GNU General Public License for more details.
15-
* *
16-
* * You should have received a copy of the GNU General Public License
17-
* * along with this program. If not, see <http://www.gnu.org/licenses/>
18-
* * *****************************************************************************
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
199
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
2014
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>
17+
* ****************************************************************************
2118
*/
2219

2320
package io.github.dsheirer.audio.codec.mbe;
@@ -32,27 +29,27 @@
3229
import io.github.dsheirer.preference.PreferenceType;
3330
import io.github.dsheirer.preference.UserPreferences;
3431
import io.github.dsheirer.sample.Listener;
35-
import jmbe.iface.IAudioCodec;
36-
import jmbe.iface.IAudioCodecLibrary;
37-
import org.slf4j.Logger;
38-
import org.slf4j.LoggerFactory;
39-
4032
import java.lang.reflect.InvocationTargetException;
4133
import java.net.MalformedURLException;
4234
import java.net.URL;
4335
import java.net.URLClassLoader;
4436
import java.nio.file.Path;
4537
import java.util.ArrayList;
4638
import java.util.List;
39+
import jmbe.iface.IAudioCodec;
40+
import jmbe.iface.IAudioCodecLibrary;
41+
import org.slf4j.Logger;
42+
import org.slf4j.LoggerFactory;
4743

4844
public abstract class JmbeAudioModule extends AbstractAudioModule implements Listener<IMessage>, IMessageListener,
4945
ISquelchStateListener
5046
{
5147
private static final Logger mLog = LoggerFactory.getLogger(JmbeAudioModule.class);
5248
private static final String JMBE_AUDIO_LIBRARY = "JMBE";
53-
private static List<String> mLibraryLoadStatusLogged = new ArrayList<>();
49+
private static final List<String> mLibraryLoadStatusLogged = new ArrayList<>();
5450
private IAudioCodec mAudioCodec;
55-
private UserPreferences mUserPreferences;
51+
private final UserPreferences mUserPreferences;
52+
private static Class sLoadedJmbeAudioConverterClass;
5653

5754
public JmbeAudioModule(UserPreferences userPreferences, AliasList aliasList, int timeslot)
5855
{
@@ -110,38 +107,67 @@ public void preferenceUpdated(PreferenceType preferenceType)
110107
protected abstract String getCodecName();
111108

112109
/**
113-
* Loads audio frame processing chain. Constructs an imbe targetdataline
114-
* to receive the raw imbe frames. Adds an IMBE to 8k PCM format conversion
115-
* stream wrapper. Finally, adds an upsampling (8k to 48k) stream wrapper.
110+
* Loads JMBE audio converter library class and then instantiates new converter instances from the loaded class.
116111
*/
117112
protected void loadConverter()
118113
{
119114
IAudioCodec audioConverter = null;
120115

121-
Path path = mUserPreferences.getJmbeLibraryPreference().getPathJmbeLibrary();
122-
123-
if(path != null)
116+
if(sLoadedJmbeAudioConverterClass == null)
124117
{
125-
try
118+
Path path = mUserPreferences.getJmbeLibraryPreference().getPathJmbeLibrary();
119+
120+
if(path != null)
126121
{
127122
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
128123
{
129-
mLog.info("Loading JMBE library from [" + path.toString() + "]");
124+
mLog.info("Loading JMBE library from [" + path + "]");
130125
}
131126

132-
URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()},
133-
this.getClass().getClassLoader());
127+
try
128+
{
129+
URLClassLoader childClassLoader = new URLClassLoader(new URL[]{path.toUri().toURL()},
130+
this.getClass().getClassLoader());
134131

135-
Class classToLoad = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader);
132+
sLoadedJmbeAudioConverterClass = Class.forName("jmbe.JMBEAudioLibrary", true, childClassLoader);
133+
}
134+
catch(IllegalArgumentException iae)
135+
{
136+
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY + getCodecName()))
137+
{
138+
mLog.error("Couldn't load JMBE audio conversion library - " + iae.getMessage());
139+
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY + getCodecName());
140+
}
141+
}
142+
catch(MalformedURLException mue)
143+
{
144+
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
145+
{
146+
mLog.error("Couldn't load JMBE audio conversion library from path [" + path + "]");
147+
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
148+
}
149+
}
150+
catch(ClassNotFoundException e1)
151+
{
152+
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
153+
{
154+
mLog.error("Couldn't load JMBE audio conversion library - class not found");
155+
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
156+
}
157+
}
158+
}
159+
}
136160

137-
Object instance = classToLoad.getDeclaredConstructor().newInstance();
161+
if(sLoadedJmbeAudioConverterClass != null)
162+
{
163+
try
164+
{
165+
Object instance = sLoadedJmbeAudioConverterClass.getDeclaredConstructor().newInstance();
138166

139-
if(instance instanceof IAudioCodecLibrary)
167+
if(instance instanceof IAudioCodecLibrary library)
140168
{
141-
IAudioCodecLibrary library = (IAudioCodecLibrary)instance;
142-
143169
if((library.getMajorVersion() == 1 && library.getMinorVersion() >= 0 &&
144-
library.getBuildVersion() >= 0) || library.getMajorVersion() >= 1)
170+
library.getBuildVersion() >= 0) || library.getMajorVersion() >= 1)
145171
{
146172
audioConverter = library.getAudioConverter(getCodecName());
147173

@@ -169,38 +195,6 @@ protected void loadConverter()
169195
}
170196
}
171197
}
172-
catch(IllegalArgumentException iae)
173-
{
174-
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY + getCodecName()))
175-
{
176-
mLog.error("Couldn't load JMBE audio conversion library - " + iae.getMessage());
177-
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY + getCodecName());
178-
}
179-
}
180-
catch(NoSuchMethodException nsme)
181-
{
182-
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
183-
{
184-
mLog.error("Couldn't load JMBE audio conversion library - no such method exception");
185-
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
186-
}
187-
}
188-
catch(MalformedURLException mue)
189-
{
190-
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
191-
{
192-
mLog.error("Couldn't load JMBE audio conversion library from path [" + path + "]");
193-
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
194-
}
195-
}
196-
catch(ClassNotFoundException e1)
197-
{
198-
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
199-
{
200-
mLog.error("Couldn't load JMBE audio conversion library - class not found");
201-
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
202-
}
203-
}
204198
catch(InvocationTargetException ite)
205199
{
206200
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
@@ -225,6 +219,14 @@ protected void loadConverter()
225219
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
226220
}
227221
}
222+
catch(NoSuchMethodException nsme)
223+
{
224+
if(!mLibraryLoadStatusLogged.contains(JMBE_AUDIO_LIBRARY))
225+
{
226+
mLog.error("Couldn't load JMBE audio conversion library - no such method exception");
227+
mLibraryLoadStatusLogged.add(JMBE_AUDIO_LIBRARY);
228+
}
229+
}
228230
}
229231
else
230232
{
@@ -235,13 +237,6 @@ protected void loadConverter()
235237
}
236238
}
237239

238-
if(audioConverter != null)
239-
{
240-
mAudioCodec = audioConverter;
241-
}
242-
else
243-
{
244-
mAudioCodec = null;
245-
}
240+
mAudioCodec = audioConverter;
246241
}
247242
}

0 commit comments

Comments
 (0)