Search Unity

Got IKVM working with Unity. Here are some things I've learned.

Discussion in 'Editor & General Support' started by jhoak, Jun 8, 2015.

  1. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    Hello everyone,

    I recently had to use IKVM for a game project with friends, and I think I spent too much time trying to work my way around errors with little documentation and general help online. So I wanted to post a few general pointers for anyone having problems.


    1) This is already on a lot of forums (this one included), but remember to go to Edit -> Project Settings -> Player and change the API Compatibility Level to .NET 2.0. Not doing this can prevent certain classes (the biggest example being System.Drawing, referenced by Swing) from being loaded from your IKVM libraries (DLLs).

    2) Make sure you add a reference in MonoDevelop for each of your IKVM DLLs, especially the ones whose names start with IKVM.OpenJDK inside the main bin folder.*

    * If you have seen anything referring to IKVM.OpenJDK.ClassLibrary.dll, that file was apparently broken up into all of the DLLs whose names start with IKVM.OpenJDK. That single DLL file no longer exists.

    3) Make sure you add your DLLs to the Assets folder. Otherwise, Unity freaks out and does not know where they are, despite your references from the 2nd step. You can add them in a subfolder if you wish, however.

    4) This may seem like kind of an obvious mistake, but it only occurred to me after an hour or 2 of testing: You cannot use objects from Java classes as fields in your scripts! E.g., you cannot do the following:

    Code (CSharp):
    1. public class MenuScript : MonoBehaviour {
    2.  
    3.        java.lang.Object obj;
    4.  
    5.        // ...
    6. }
    Again, Unity has no idea what to do with Java fields, as they are basically foreign objects to Unity and its C# libraries.

    5) That said, you also cannot use Java types as method parameters or return types.* Again, Unity has to process this type when it looks at your script's methods, and Unity will just see your Java types as foreign.**

    *I have NOT tested private methods or private/inner class methods, only public outer-class methods. But I fear a similar result applies.
    **I know, you JUST imported those libraries as assets, but that's the way Unity works.


    6) This is kind of obvious also, but you should put in a using statement for the java.lang namespace. Remember that unlike Java, C# and IKVM will not import it for you (haha). You have to add it yourself.

    7) On a final note, remember that the IKVM equivalents of Java classes do not necessarily behave just like the actual Java classes. Objects may be serialized or streamed quite differently between Java and IKVM, for instance.


    These 7 things basically summarize the issues I had to deal with, but if anyone else has dealt with other issues and found solutions, feel free to post your experiences here. Thanks for reading, and I hope this helps anyone trying to get Unity to work with IKVM.:)
     
    Last edited: Jun 8, 2015
  2. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    I have been working on this for some time but I am constantly getting the same error type or namespace for the dll's method is not recognized. Could you please post a snippet of code showing your "using" and maybe how you reference the dll? I have been searching everywhere to find the info it's just not out there and no one likes sharing code or anything :( Thanks a ton!
    Jason
     
  3. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    These are the using statements I wrote for the IKVM libraries.

    Code (CSharp):
    1. using java.lang;
    2. using java.io;
    3. using java.net;
    I think if your DLL references are right, MonoDevelop will bring up an auto-complete menu while you're typing these statements. So you could type "using java." and it should bring up lang, io, net, etc.

    Will post my references menu shortly (I have to reinstall Unity).

    Edit: More like 1 hour. 1.3gb download at ~250 kbps...
     
    Last edited: Sep 2, 2015
  4. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    Just checked my references -- I think I remember what I did to get my references working:

    1) Make a subfolder in your project's Assets folder, and name it IKVM or "IKVM Files" or something.
    2) Drag and drop all of your IKVM files and folders into this directory. Unity may hassle you about the two copies of JVM.DLL for some reason; you can delete the one inside "bin-x64".
    3) Go to "Edit References" in MonoDevelop, click the ".Net Assembly" tab, and navigate to Assets/bin. From there, select all of your DLLs that begin with "IKVM" (all capital letters!) and add them as references.

    If you have any DLLs that you manually converted from Java to C# using IKVM, you will want to place them in your new folder also.
     
  5. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    Hey thanks for all the help, unfortunately I am still getting a error for type or namespace not found for my Java class :( I am on a mac, wonder if that makes a difference.
    If you have anymore thoughts please let me know, otherwise thanks for the help, much appreciated.

    Jason
     
  6. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    Can you post the complete error Unity gives you? I remember having the same error (on Windows, though) and figuring it out after a while.

    If it gives you a line number for the error I'd like to see the line of code also, if it's not too much trouble.
     
  7. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using TMPro;
    4. using java.lang;
    5. using java.io;
    6. using java.net;
    7.  
    8. public class PrintToTmPro : MonoBehaviour {
    9.  
    10.     HelloWorld helloWorld = new HelloWorld();
    11.  
    12.  
    13.     void Start(){
    14.  
    15.     }
    16.  
    17.     void Update () {
    18.         string s= helloWorld.hello();
    19.  
    20.         this.GetComponent<TextMeshPro>().text = s;
    21.     }
    22. }
    23.  
    error from Unity is as follows


    Assets/scripts/PrintToTmPro.cs(10,9): error CS0246: The type or namespace name `HelloWorld' could not be found. Are you missing a using directive or an assembly reference?
     
  8. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    I am thinking it's possibly the jar / dll file is not correct somehow... not converted or exported properly :( but I'm not sure.
     
  9. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    Your issue is line 10:

    Code (CSharp):
    1. HelloWorld helloWorld = new HelloWorld();
    I'm assuming HelloWorld is a class in your TMPro library/package, and I'm also assuming TMPro is a DLL you made through IKVM's converter.

    Unity won't let you make a field of the type HelloWorld, or of any other class in TMPro. Also you cannot make a field with a converted Java class as its type, like I mentioned in point (4) of my first post.

    You can, however, use variables of type HelloWorld within your methods. So you can do:
    Code (CSharp):
    1. void Start() {
    2.          HelloWorld helloWorld = new HelloWorld();
    3.  
    4.          // other code below...
    5.  
    6. }
     
  10. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    Ahh, hmm... ok I will try that and see how that goes. TMpro is actually textmesh pro which is a plugin, my dll does however have that class of HelloWorld. Thanks I will try that and see how it goes.
     
  11. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    mmm.... I tried to make a pointer to the class as seen in the using com.name.id (changed as this is company stuff) etc etc
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using TMPro;
    4. using java.lang;
    5. using java.io;
    6. using java.net;
    7. using com.name.id;
    8.  
    9. public class PrintToTmPro : MonoBehaviour {
    10.    
    11.     void Start(){
    12.  
    13.         HelloWorld helloWorld = new HelloWorld();
    14.         this.GetComponent<TextMeshPro>().text = helloWorld.hello();
    15.     }
    16.     // Update is called once per frame
    17.     void Update () {
    18.     //    string s= helloWorld.hello();
    19.  
    20.     //    this.GetComponent<TextMeshPro>().text = s;
    21.     }
    22. }
    23.  
    this gives no errors but when ran it gives this error


    SpritePacker failed to get types from HelloWorld, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null. Error: The classes in the module cannot be loaded.
    UnityEditor.Sprites.Packer:GetSelectedPolicyId()
     
  12. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    Comment out line 14 of that code and try this, just to see what happens:
    this.GetComponent<TextMeshPro>().text = null;

    Let me know if it generates an error. If so, Unity might not like you trying to get a component of type TextMeshPro (though it should be OK with that).

    Otherwise, the call helloWorld.hello() might be a problem.
     
  13. LaughingGull

    LaughingGull

    Joined:
    Jul 8, 2012
    Posts:
    37
    not a tmpro error :( I think it's either the dll or trying to making it work on Mac :( thanks for the help man
     
  14. jhoak

    jhoak

    Joined:
    May 30, 2015
    Posts:
    7
    Sure thing. You could remake the dll and try again. Also make sure your Java classes in that package aren't referencing any classes you made outside the package, or external Java addons, etc. You need all of your associated Java classes to be in libraries referenced and used in MonoDevelop.
     
  15. aymenr

    aymenr

    Joined:
    Oct 13, 2015
    Posts:
    1
    Hi jhoak, im trying to use the gephi java library in my unity application.
    I need to access the .class attribute of one of my classes. C# cant seem to find it.

    org.gephi.project.api.ProjectController pc = org.openide.util.Lookup.getDefault().lookup(typeof(org.gephi.statistics.plugin.Degree));


    I came across this on the ikvm sourceforge wiki (http://sourceforge.net/p/ikvm/wiki/Using_Java_with_.NET/):
    Some Java syntax is not compatible and need some hacks and has some specific notation.

    Java C#

    class operator
    Class clazz = com.mypack.MyClass.class;
    Class clazz = typeof(com.mypack.MyClass)


    After this i've tried writing
    org.gephi.project.api.ProjectController pc = org.openide.util.Lookup.getDefault().lookup(typeof(org.gephi.statistics.plugin.Degree));

    to which it says that it cannot implicitly convert type object to the Degree class. I tried casting this class into a java object but that doesent seem to work. Would super appreciate some help on this.
     
  16. LoadingUserName

    LoadingUserName

    Joined:
    Feb 12, 2018
    Posts:
    1
    Hi,

    Similar to the OP, I was pulling out my hair trying to figure out several errors for the past several hours. I'm posting these in hopes that they'll be useful to someone else.

    For reference:
    (I was using IKVM to convert my own library from a .jar to an equivalent .dll)
    • IKVM Version: 8.1.5717.0
    • Java Version: OpenJDK 8 from Redhat (using the java 11 compiler didn't produce the right class file format in the exported .jar and IKVM threw errors when trying to convert said .jar file)
      • running "java -version" in cmd prompt print out the following
      • openjdk version "1.8.0_282"
      • OpenJDK Runtime Environment (build 1.8.0_282-b08)
      • OpenJDK 64-Bit Server VM (build 25.282-b08, mixed mode)
    • Unity Version 2020.3.0f1 (this is less important, but make sure the .net API version in the project settings is set to .net 2.0 only)

    Issues:

    1. warning IKVMC0101: Unable to compile class "<classname>"
      (class format error "<classname> (55.0)")
    Solution: use java 8 to compile jar file, if you have two versions installed, you may need to edit your environment variables (i just removed 11 completely cause I don't plan to use it much at all)

    2. Errors in the Unity Console about the IKVM dlls being unable to cmpile

    Solution: I know many others said to just copy all the files into your asset folder, but I personally found better results by adding them one by one, starting first with my custom library, which would then trigger the console to specify IKVM.OpenJDK.Core.dll as a missing dependancy. I'd add that to my asset folder, which would then trigger another call for it's referecned dlls. I just added them one at a time and only ended up using abut 16 of the 28 in the bin folder - YMMV if you used different java libraries in your java source or need access to different java libraries than I did.

    3. "<ClassName>" does not contain a constructor that takes 0 argumets
    Solution : This one took me a good while to figure out, as I wasn't able to instantiate class instances via their constructors. I realized the solution is to explicity denote your class constructor (and the class itself) as public by placing "public" before the constructor definition (and class defninition) in the .java source
    Edit:
    I also found this link helpful in verifying my steps and that I wasn't crazy.
    http://emi.gd/blog/unity-and-java-marriage/

    Hope this helps and all the best.