1. Getting started
- 1.1. Installing Javonet
- 1.2. Activating Javonet
- 1.3. Adding References to .NET Libraries
- 1.4. XML Configuration File
- 1.5. Using the Javonet Fluent Interface
- 1.7. Introduction to Using .NET Back-end and UI Components in Java
2. Calling methods
- 2.1. Invoking Static Methods
- 2.2. Creating Instance and Calling Instance Methods
- 2.3. Calling Generic Methods
3. Working with .NET Objects
- 3.1. Creating Instance Of Generic Object
- 3.2. Extending the .NET Class in Java and Wrapping .NET Methods
4. Fields and Properties
- 4.1. Get/Set Values for Static Fields and Properties
- 4.2. Get/Set Values for Instance Fields and Properties
5. Methods Arguments
- 5.1. Passing Reference-Type Arguments
- 5.2. Passing Arguments by Reference with “ref” and “out” Keywords
- 5.3. Passing typeof(Type) as Method Argument
- 5.4. Calling Overloaded Method Passing Null Argument
6. Nested Types
7. Enums
8. Arrays and Collections
- 8.1. Arrays: Using Value-Type and Reference-Type Arrays
- 8.2. Working with .NET arrays and collections from Java with Javonet
9. Embeding UI controls
10. Referencing libraries
11. Off-line activation
12. Events and Delegates
13. Disposing and Garabage Collection
14. .NET Configuration Files (AppConfig, WebConfig)
15. Exceptions, Debugging and Testing
- 15.. Handling Activation Issues
- 15.1. Handling .NET Exceptions
- 15.2. How to debug .NET code called from Java
- 15.3. Debugging Javonet Enabled Application
16. Strongly-Typed Wrappers
17. Advanced Activation and Licensing
- 17.1. Runtime vs. Offline vs. Compile Time Activation
- 17.2. Project Activation Tool
- 17.6. Delegating Activation Server
18 Other usage scenarios
How to debug .NET code called from Java
Both for .NET and Java, one of the most important features provided by an IDE is the ability to track code
execution at runtime. Either when looking for bugs in the dynamic portion of code or verifying correctness of
a complex algorithm – debugging brings unqestionable improvement into development process.
In case of the Javonet users dealing with the debugging task, its importance doubles as relating to both
supported domains: .NET and Java. Let’s see how easily this can be achieved and applied against any
managed assembly.
Workspace
For the purpose of this example, I’ll be using the following .NET class representing a simple Person entity,
having two properties Firstname and Lastname, and being able to return a DisplayName, being a trivial
concatenation of the former:
using System; namespace com.javonet.tutorial.debugging { public class Person { public String Firstname { get; set; } public String Lastname { get; set; } public String DisplayName() { return Firstname + " " + Lastname; } } }
The Java code that will interoperate with our Person class is as follows:
package com.javonet.tutorial.debugging; import com.javonet.Javonet; import com.javonet.JavonetException; import com.javonet.JavonetFramework; import com.javonet.api.NObject; import static com.javonet.tutorial.debugging.Constants.EMAIL; import static com.javonet.tutorial.debugging.Constants.LICENSE_KEY; import static com.javonet.tutorial.debugging.Constants.DLL_FILE_PATH; public class Main { public static void main(String[] args) throws JavonetException { Javonet.activate(EMAIL, LICENSE_KEY, JavonetFramework.v45); Javonet.addReference(DLL_FILE_PATH); NObject person = Javonet.New("Person"); person.set("Firstname", "Marcin"); person.set("Lastname", "Pokora-Janda"); String displayName = person.invoke("DisplayName"); System.out.println(displayName); } }
Let’s dig a little around what happens in the code:
Line 16 – activates Javonet framework using provided credentials and JavonetFramework argument,
successfull execution of this step loads CLR within Java process, allowing our .NET debugger to be
attached
Line 17 – instructs Javonet to load classes referenced in the DLL library file under given path into the CLR,
this makes our Person class accessible
Line 19-21 – these lines instantiate a new Person class object and set its properties to relevant values
Line 23 – invokes Person object’s DisplayName method and stores its return value in local String
variable
Line 24 – prints resultant DisplayName value from .NET code to standard output of Java process
Debugging Procedure
Since debugging happens at runtime, we’ll start by launching our Java code. As already mentioned, it’s
important to activate Javonet before attempting to place any breakpoint on Java side of our solution, as this
will start CLR within our process. Let’s put a breakpoint right after the activate method, as presented
below.
Now let’s switch to our Visual Studio and attach a debugger to the newly started Java process with CLR. In order to do that, go to Debug > Attach to Process, and select appropriate javaw.exe process. Notice that its Type value should indicate that it’s hosting managed code using .NET version matching the one we’ve specified in Javonet activate method using JavonetFramework argument.
We’re almost ready to start debugging. Let’s put a breakpoint in the body of Person’s class DisplayName method. Notice that the breakpoint circle symbol is hollow inside, since the debugging symbols have not been loaded into CLR yet
On Java side, let’s move one step forward by putting a breakpoint on line 19. Calling addReference method loads our DLL library which should result in Person class becoming available for debugging in Visual Studio.
As you can see, the circle symbol is now completely filled. At this point our breakpoint will get hit once the DisplayName method is invoked on Java side.
In Eclipse, let’s proceed with code execution until line 23 is reached. Passing this point will result in hitting breakpoint in Visual Studio.
As you can see, we can now use .NET debugger for all our intended activities, like variables’ inspection, runtime values modification etc.
Once our work with debugging Person class is done and normal code execution is resumed, it’ll be transferred back to Java, as it is shown with the breakpoint in line 25.
As the program finishes, we’ll get a returned display name value of our Person object instance.
Debugging Without .NET Source Project
Presented debugging method is available also in situations when we do not have access to library source code, provided that the related debugging symbols .pdb file for analysed program or library is available on the Javonet classpath at runtime. We would also need to know full namespace, class name and target method, where to put a breakpoint.
Rerun Java code from Eclipse, breaking its execution at line 17 to launch a new Java CLR-enabled process.
In Visual Studio make sure you’ve closed solution for our previous example. As done before, attach debugger to respective managed javaw.exe process.
Our next step would be to insert new breakpoint. As we do not have the source code available, we’ll need to specify its location manually. In order to do that we can go either to the breakpoint window New > Break at function, go to Debug > New Breakpoint > Break at function or use the Ctrl + B shortcut. Any of these paths will result in opening new window where we’re asked to put the location of our breakpoint by specifying fully qualified method name.
Once we are happy with our input, Visual Studio might notify us about not being able to find the specified location, which is understandable due to lack of source code. After accepting this notification we should be presented with a breakpoint entry similar to the one in the following picture. The circle will be hollow again, since we’ve not loaded our .NET library via Javonet API yet.
If we proceed with Java code execution past line 17, the breakpoint symbol will again get filled, similarily to how it behaved in previous example. Also, the breakpoint location now contains fully qualified signature of the targeted method.
At this point, we are ready to debug our .NET application, therefore let’s proceed with Java code execution. Running line 23 will hit our specified breakpoint, returning control to Visual Studio, where we’ll be presented with a source code generated based on the supplied debugging symbols file.
Summary
In this article we’ve learnt how to properly attach Visual Studio debugger to Java proces hosting CLR managed code run by Javonet. The approach has been presented for two scenarios, distinguished by the availability of source code, proving easy access to all of the features offered by Visual Studio debugger that can be used during development of Java application using .NET libraries, drivers or SDKs with Javonet.