- Undocumented Matlab - https://undocumentedmatlab.com -
Java class access pitfalls
Posted By Yair Altman On July 2, 2014 | 8 Comments
A few days ago I consulted to a company that wanted to integrate some of their Java code in Matlab. The Java code compiled ok and ran just fine in the Java environment, but when we wanted to use the relevant Java classes in Matlab we got all sorts of errors. Since I believe that this could be a common problem, and I’m not sure that there’s any other place that does this, I thought to list the possible error causes in today’s article:
>> jObject = JButton('Click me!'); % missing package name Undefined function 'JButton' for input arguments of type 'char'. >> jObject = java.swing.JButton('Click me!'); % should be javax.swing... Undefined variable "java" or class "java.swing.JButton". >> jObject = javax.Swing.JButton('Click me!'); % should be javax.swing... Undefined variable "java" or class "javax.Swing.JButton". >> import java.swing.* % should be javax.swing... - no error here, only in the next line >> jObject = JButton('Click me!'); % missing package name Undefined function 'JButton' for input arguments of type 'char'. >> import java.swing.JButton % should be javax.swing... Error using import Import argument 'java.swing.JButton' cannot be found or cannot be imported.
Note: package names are typically lowercase, but 3rd-party packages might not follow this convention! Since Java is case-sensitive, the package name must be exact.
>> a = MyJavaClass; Undefined function or variable 'MyJavaClass'. >> a = my.java.Class; Undefined variable "my" or class "my.java.Class".
To get Matlab’s current JVM version, use the version command:
>> version -java
ans =
Java 1.7.0_11-b21 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
The default JVM used in Matlab R14 (7.0) to R2013a (8.1) was 1.6 (=JDK 6); R2013b (8.2) and later use 1.7 (=JDK 7). If you wish to ensure compatibility with earlier Matlab releases, I suggest compiling using JDK 6 rather than 7 or 8. This can easily be modified in all Java IDEs, in the project’s preferences. Remember to reference the corresponding JRE 1.6 libraries as well, rather than the newer JRE ones. In many cases, the Java code would still compile and run properly, even when compiled using the earlier JDK/JRE.
If downgrading the compilation JDK is not possible (for example, if you do not have access to the source code, or if it uses some new JDK features), then consider installing a newer compatible JVM in Matlab [1].
Note that when we try running the Java classes using the java executable (outside Matlab), we do get a meaningful message about the fact that the classes were compiled for a higher JVM version. Unfortunately, this information is simply not being provided by Matlab – just the standard plain error about the function or file not being found. I hope this will be fixed in some future Matlab release.
public
classes. If the class is private
, protected
or has package visibility (by not specifying any visibility modifier at all), then the class would not be loadable by Matlab, only by other Java classes. So remember to add the public
keyword in the definition of all the Java classes that you wish to directly use in Matlab.public
constructors. If all the class constructors are non-public
, then Matlab cannot create a class instance object. In such a case we would get a misleading error message, that at least hints that the problem is with the constructor:
>> jObject = MyJavaClass();
No constructor 'MyJavaClass' with matching signature found.
Note that using private constructors is common practice for singleton designs. In such cases we might find a public static
class method that returns the class reference (e.g., MyJavaClass.getInstance()).
int
, and we try to pass a standard Matlab number (which is a double). In such cases, a simple solution could be to either modify the class, overloading the constructor to also accept double, or to type-cast the inputs in Matlab to the relevant type expected by a constructor:
jObject = MyJavaClass(int32(value));
>> jObject = MyJavaClass();
Java exception occurred:
java.lang.OutOfMemoryError: PermGen space
The solution in this case is to create a java.opts file in Matlab’s startup folder, that contains a higher specification of the maximal allowed PermGen space. The java.opts file is a simple text file that is automatically loaded by Matlab [10] when it starts its internal Java engine. For example, to set the initial PermGen space to 64MB and the maximal PermGen space to 256MB, include the following lines in java.opts:
-XX:PermSize=64m
-XX:MaxPermSize=256m
An alternative solution that might help in some cases is to load the new classes on Matlab’s static Java classpath, rather than on the dynamic classpath (see item #4 above).
Any other pitfalls I forgot to mention? Let us know in a comment below.
p.s. – the javaclasspath function has an undocumented input parameter: specifying -v0, -v1 or -v2 sets the Java classloader’s verbosity level to the relevant value. If you don’t know what this means, then you probably don’t need to use this feature…
Categories: Java, Low risk of breaking in future versions, Undocumented feature
Article printed from Undocumented Matlab: https://undocumentedmatlab.com
URL to article: https://undocumentedmatlab.com/articles/java-class-access-pitfalls
URLs in this post:
[1] installing a newer compatible JVM in Matlab: http://undocumentedmatlab.com/blog/using-java-7-in-matlab-r2013a-and-earlier
[2] javaaddpath: http://www.mathworks.com/help/matlab/ref/javaaddpath.html
[3] these undocumented hacks: http://undocumentedmatlab.com/blog/static-java-classpath-hacks
[4] Read here: https://www.mathworks.com/help/matlab/matlab_external/java-class-path.html
[5] only exists since R2012b: http://undocumentedmatlab.com/blog/matlab-installation-take-2
[6] javaclasspath: http://www.mathworks.com/help/matlab/ref/javaclasspath.html
[7] indeed be nerve wrecking: https://www.mathworks.com/matlabcentral/newsreader/view_thread/314610
[8] another example: https://www.mathworks.com/matlabcentral/newsreader/view_thread/164273
[9] see here: https://stackoverflow.com/questions/3722920/java-how-to-check-current-perm-permgen-size
[10] automatically loaded by Matlab: https://www.mathworks.com/help/matlab/matlab_env/java-opts-file.html
[11] Accessing internal Java class members : https://undocumentedmatlab.com/articles/accessing-internal-java-class-members
[12] Extending a Java class with UDD : https://undocumentedmatlab.com/articles/extending-a-java-class-with-udd
[13] Static Java classpath hacks : https://undocumentedmatlab.com/articles/static-java-classpath-hacks
[14] Matlab callbacks for Java events in R2014a : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events-in-r2014a
[15] Matlab callbacks for Java events : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events
[16] Creating a simple UDD class : https://undocumentedmatlab.com/articles/creating-a-simple-udd-class
Click here to print.
Copyright © Yair Altman - Undocumented Matlab. All rights reserved.
8 Comments To "Java class access pitfalls"
#1 Comment By waldroje21 On May 1, 2015 @ 08:22
Any idea why a Matlab would recognize a Java class file from the Dynamic path, but not the Static? I’ve added it to my Static path, and it’s in there… but does not work… when I then add the same path using javaaddpath , it works.
#2 Comment By Yair Altman On May 1, 2015 @ 08:26
Perhaps one or more of the following happened:
* you edited the wrong classpath.txt file
* you forgot to restart Matlab after editing the classpath.txt file
* you mistyped the class’s full path in the file
* you used a relative path in the file
#3 Comment By waldroje21 On May 1, 2015 @ 13:21
in regard to the first… it shows up on the bottom when I type javaclasspath in the workspace, so I assume it can’t be the wrong file, and that path is what i get when i type prefdir… I definitely restarted Matlab…. and I’m using the same exact file string in the Dynamic path, that I use in the javaclasspath.txt, i just copied it straight from terminal. I’ve done this with no problem on 3 other installs, so it’s a bit strange.
#4 Comment By Yair Altman On May 2, 2015 @ 10:18
If you wish me to help you debug your specific installation, contact me by mail for a private consulting.
#5 Comment By Vincent On March 16, 2016 @ 20:38
How about what to do when you get a “
java.lang.NoSuchFieldError
” because your java code uses a version of Apache’s httpcore that is newer than the one matlab ships with, and the old one seems to be creating conflicts with the newer one you’ve added to your java path?#6 Comment By Malcolm Lidierth On March 16, 2016 @ 22:26
The class loader will only load one copy of a specific package/class combination. A newer version will not replace the older one even if you have called javaaddpath (hence the NoSuchFieldError which implies you have created an instance using the old code). This is a Java class loader feature: if you load a jar that has dependencies on other jars (e.g. in a /dist/lib folder), and some of those jars are already loaded, the already loaded versions will continue to be used.
In general, open source projects with the Apache brand will maintain backwards compatibility – deprecating, but not removing, old fields/methods. If backwards compatibility is not maintained Apache projects will usually alter the package names so both versions can be used simultaneously. This being the case, replacing the jar file shipped with MATLAB with the newer version should produce no problems. But, anyone else using your code will need to do that too. Buyer beware.
#7 Comment By Amaury Vanvinckenroye On October 19, 2016 @ 14:26
Hi, I’m using some Java classes in a Matlab code and it seems that a specific java class is not loaded, but only at the first run (i.e. at the start of Matlab). Later calls to the java function don’t give any error, even if I “clear all; clear classes; clear java”. Here’s the part of code failing at first run.
The failing java class is ServerAdress and is part of the mongodb package.
Other java classes run fine immediately.
This error doesn’t occur on all computers, so I’m giving you my specs.
Windows 10 (previously windows 8), Matlab R2013a with Java 1.6.0_17-b04 (also tried with Java 1.8.0_25-b18 when adding it as environment variable).
It worked on a Mac with Matlab R2015b with Java 1.7, but also failed on another Mac with Matlab R2014a and java 1.8.
Thanks in advance
#8 Comment By Yair Altman On October 20, 2016 @ 20:29
@Amaury – this seems to be something specific to the
MongoClient
class. You should probably ask about this in the MongoDB forums.