Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1854
  • Last Modified:

JNI problem wenn calling c# class

Hi all
I have a java class calling a piece of C# code.
all is fine when I return a string like:
return "blablabla"; form the C# class

I want to do more then just return a static string. The problem is that I get following errors

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (0xe0434f4d), pid=5320, tid=4832
#
# JRE version: 6.0_23-b04
# Java VM: Java HotSpot(TM) Client VM (19.0-b09 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [KERNELBASE.dll+0xb727]
#
# An error report file with more information is saved as:
# C:\Users\tba\Documents\NetBeansProjects\APP6IconProvider\hs_err_pid5320.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

as soon as I try to instantiate any thing in the C# class

Source Snippet List:
MSSCall -> the calling Java class
Mapper.h  -> c++ unmanaged
Mapper.cpp -> jni interface implementation
Caller.h -> c++ managed
Caller.cpp  -> entry point to the C# world
Wrapper.cs -> the actual c# code (which should do more....load and use a partner dll)

The C++ and the C# project are in the same solution.
The C++ Project generates a Caller.dll, which i copy into the Java Project folder
The Solution generate a MSS2Java.dll which is signed and added to the GAC using gacutil.exe -if.

What must be done to be able to use another dll on the C# side (Wrapper.cs) with out receiving error. See also the erro log attached
//Wrapper.cs
using System;
using System.Text;
using System.Collections.Generic;

using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;

using Interop.MssComServer;
using System.Configuration;

namespace MSS2Java
{
    public class Wrapper
    {
        private AppSettingsReader config;
       
        public Wrapper()
        {
            config = new AppSettingsReader();
        }

public String genIcon(String symbolID)
        {
            return  (String)config.GetValue("terrainview_config", typeof(String));
        }

    }
}

Open in new window

// Caller.h
#pragma once
#include <string>
//--------------------------------
/*
Native dll import (this is the thing we want to use in our java code)
*/
#import "..\lib\TLB\MssComServerV3.tlb" rename("LoadLibrary", "MssLoadLibrary")
//--------------------------------

namespace mss {
	public ref class Caller
	{
		public:
			Caller();
			System::String^ callWrapper(System::String^ app6String );
	};
}

Open in new window

//Caller.cpp
// This is the main DLL file.
#using <mscorlib.dll>
#include <string>
#include "stdafx.h"
#include "atlbase.h"

//------------------------------
/*
This is the C# dll we implemented, which is using the native one
*/
#using <MSS2Java.dll>
//------------------------------

#include "Caller.h"

using namespace MSS2Java;

namespace mss
{
	//constructor
	Caller::Caller()
	{
	}
	
	//Method entering the C# environment
	System::String^ Caller::callWrapper(System::String^ app6String)
	{
		//Instantiate the C# class
		MSS2Java::Wrapper^ w = gcnew MSS2Java::Wrapper();
		//Call the C# method (this method, on the c#-side is actually calling the native dll (the one delivering the 
		//added value all the reste is only piping throught the different worlds :-)
		System::String^ s = w->genIcon(app6String);
		return s;
	}

};

Open in new window

//Mapper.h
#include <jni.h>
//-----------------------------
/*
Interface between the java world and the c++ world
With "pragma" we specify that this is unmanaged code
*/
#include "mcp_icongen_gssoft_MSSCall.h"
//-----------------------------

//-----------------------------
/*
With "pragma" we specify that this is unmanaged code
*/
#ifdef _MANAGED
#pragma managed(push, off)
#endif

JNIEXPORT jstring JNICALL Java_mcp_icongen_gssoft_MSSCall_genIcon (JNIEnv *, jobject, jstring app6String);

#ifdef _MANAGED
#pragma managed(pop)
#endif
//-----------------------------

Open in new window

//Mapper.cpp
#include <jni.h>
#include <vcclr.h>

#include <msclr/marshal.h>

#include "stdafx.h"
#include "Mapper.h"
#include "Caller.h"
#include "mcp_icongen_gssoft_MSSCall.h"

#using <MSS2Java.dll>
using namespace MSS2Java;

JNIEXPORT jstring JNICALL 
  Java_mcp_icongen_gssoft_MSSCall_genIcon (JNIEnv *env, jobject obj, jstring app6String) {

     const jchar* app6Def = env->GetStringChars(app6String, NULL);
     if (app6Def == NULL) {
         return NULL; /* OutOfMemoryError already thrown */
     }
	System::String^ managedString = gcnew System::String((const wchar_t*)app6Def);

    env->ReleaseStringChars(app6String, app6Def);

/////////////////////////////////////////////////////////
    //Instantiate the MC++ class.
    mss::Caller^ c = gcnew mss::Caller();

    // The actual call is made. 
	System::String^ pathToIcon = c->callWrapper(managedString);
	return env->NewStringUTF ((const char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(pathToIcon).ToPointer());
/////////////////////////////////////////////////////////	
//	return 0;
}

Open in new window

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (0xe0434f4d), pid=5320, tid=4832
#
# JRE version: 6.0_23-b04
# Java VM: Java HotSpot(TM) Client VM (19.0-b09 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [KERNELBASE.dll+0xb727]
#
# An error report file with more information is saved as:
# C:\Users\tba\Documents\NetBeansProjects\APP6IconProvider\hs_err_pid5320.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

Open in new window

// java class 
package mcp.icongen.gssoft;

/**
 *
 * @author tba
 */
//import java.util.*;

public class MSSCall {
    static {
        System.loadLibrary("Caller");
    }
    /*
     * Native method declaration
     * Returning the path to the generated icon
     */
    private native String genIcon(String app6def);

    public static void main(String[] args)
    {
        MSSCall call = new MSSCall();
        System.out.println("The new icon can be found at: "+call.genIcon("IUSPS----------"));
    }

}

Open in new window

hs-err-pid2944.log
0
thomasbau65
Asked:
thomasbau65
  • 9
  • 9
1 Solution
 
Carlos VillegasFull Stack .NET DeveloperCommented:
I think that you must use this:
byte[] assemblyBytes = File.ReadAllBytes("C:\\MyDynamicAssembly.dll");
Assembly assembly = AppDomain.CurrentDomain.Load(assemblyBytes);

Open in new window

0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
More clear:
//Wrapper.cs
using System;
using System.Text;
using System.Collections.Generic;

using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;

using Interop.MssComServer;
using System.Configuration;


namespace MSS2Java
{
    public class Wrapper
    {
        private AppSettingsReader config;

        public Wrapper()
        {
            // Ready assembly bytes.
            byte[] assemblyBytes = System.IO.File.ReadAllBytes("C:\\MyAssembly.dll");

            // Load into current appdomain.
            System.Reflection.Assembly assembly = AppDomain.CurrentDomain.Load(assemblyBytes);

            // Create a class instance.
            object myClassInstance = assembly.CreateInstance("MyNamespace.MyClass").GetType();
            
            // My class type.
            System.Type myClassType = myClassInstance.GetType();

            // Invoque MyClass.MyMethod
            string myTestValue = (string)myClassType.GetMethod("MyMethod").Invoke(myClassInstance, null);


            config = new AppSettingsReader();
        }

        public String genIcon(String symbolID)
        {
            return (String)config.GetValue("terrainview_config", typeof(String));
        }
    }
}

Open in new window

0
 
thomasbau65Author Commented:
Hi yv989c
Thanks for the answer.
I presume that MyDynamicAssembly.dll is the dll build when compiling the c#/c++ solution. in my case the MSS2Java.dll. I further get from the syntax that you suggest putting your code in the c# file Wrapper.cs

I tried that. The error stay the same.
I also called the Wrapper.cs directly with out passing through the java-jni stuff. The response from the vshost is "no symbols loaded"

May be I got something wrong.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
thomasbau65Author Commented:
oops i was to quick
I try your code
thanks
0
 
thomasbau65Author Commented:
Hi yv989c
Ok
the code works; I can call and instantiate a class from the native-partner dll great;
How can I use the Invoque MyClass.MyMethod part and pass it parameter to the invoked method?
thanks


0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Sure:
 .Invoke(myClassInstance, null);

Replace null with an object array (yours parameters)
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Example passing different types to your method:
string myTestValue = (string)myClassType.GetMethod("MyMethod").Invoke(myClassInstance, new object[] {"hello", 123, DateTime.Now, new string[] {"A", "B", "C"}});

Open in new window

0
 
thomasbau65Author Commented:
Hi yv898c
The code below , when used from a simple C# project is running perfectly.

The used dll is an Interop from a basic Com.dll
Further the “MssSymbolProviderServiceGS” is an interface but instantiate with new. As I said the code runs and all is ok

My problem is that I have to use the COM via JNI.
But my code is throwing error saying that some for instance the “t_SymbolProvider” Type can only by instantiate in combination with the method GetTypeFromProgID(). But the method is not available...

Further I'm not sure if the implementation of the method (invokeMember) as such as been understood...

I can not provide the dll as such but have added the documentation. (Moderator note: file has been removed.  modus_operandi)

Thanks for helping me out.
public Wrapper()
        {
           
            // Ready assembly bytes.
            byte[] assemblyBytes = System.IO.File.ReadAllBytes(
                "C:\\Interop.MssComServer.dll"
                );

            // Load into current appdomain.
            System.Reflection.Assembly assembly = AppDomain.CurrentDomain.Load(assemblyBytes);
            
            Type[] typeArray = assembly.GetTypes();

            foreach (Type type in typeArray)
            {
                if (type.IsClass == true)
                {
                    Console.WriteLine("...Found Class : {0}", type.FullName);
                }
                // If it does not implement the IBase Interface, skip it
                if (type.GetInterface("Interop.MssComServer.MssSymbolProviderServiceGS") == null)
                {
                    continue;
                }

                object i_symbolProviderService = Activator.CreateInstance(type);
                Console.WriteLine(".....SymbolProviderService instantiate");

                /*
                 * Object InvokeMember (
                    string name,
                    BindingFlags invokeAttr,
                    Binder binder,
                    Object target,
                    Object[] args,
                    ParameterModifier[] modifiers,
                    CultureInfo culture,
                    string[] namedParameters
                )
                */


                object[] param = new object[] { "C:\\Program Files (x86)\\gs-soft\\MSS\\MssLibrary\\MssLibrary_Point.mssz", 200 };               
                object symbolProvider = type.InvokeMember("LoadLibrary",
                                            BindingFlags.Default | BindingFlags.InvokeMethod,
                                            null,
                                            i_symbolProviderService,
                                            param);

                Type t_SymbolProvider = symbolProvider.GetType();
                Console.WriteLine(".....ProviderService instantiate");


                param = new object[] { "<Symbol ID=\"SFGPUCI---AFSZG\"><Attribute ID=\"M\">4</Attribute><Attribute ID=\"T\">3</Attribute></Symbol>"};
                object SymbolProviderString = type.InvokeMember("CreateApp6aObjStr",
                                            BindingFlags.Default | BindingFlags.InvokeMethod,
                                            null,
                                            i_symbolProviderService,
                                            param);
                Console.WriteLine(".....Calling CreateApp6aObjStr");

                object SymbolProviderFormat = type.InvokeMember("CreateFormatObj",
                                            BindingFlags.Default | BindingFlags.InvokeMethod,
                                            null,
                                            i_symbolProviderService,
                                            null);
                Console.WriteLine(".....Calling CreateFormatObj");

                param = new object[]{SymbolProviderString, SymbolProviderFormat};
                object i_SymbolProvider = Activator.CreateInstance(t_SymbolProvider);
                object SymbolProviderGraphic = t_SymbolProvider.InvokeMember("CreateSymbolGraphic",
                                            BindingFlags.Default | BindingFlags.InvokeMethod,
                                            null,
                                            i_SymbolProvider,
                                            param);


                param = new object[]{"C:\\thomas.bmp"};
                Type t_SymbolProviderGraphic = SymbolProviderGraphic.GetType();
                object  i_SymbolProviderGraphic = Activator.CreateInstance(t_SymbolProviderGraphic);

                t_SymbolProviderGraphic.InvokeMember("ExportToFile",
                                            BindingFlags.Default | BindingFlags.InvokeMethod,
                                            null,
                                            i_SymbolProviderGraphic,
                                            param);
                
                break;
            }

Open in new window

MssSymbolProviderServiceGS mSymbolProviderService = new MssSymbolProviderServiceGS();
            MssSymbolProviderGS mSymbolProvider = mSymbolProviderService.LoadLibrary(
                "C:\\path\\to\\my\\lib.mssz", 200);
            MssApp6aStringObjGS mFatSymbolProviderString = mSymbolProviderService.CreateApp6aObjStr(app6Def);
            MssSymbolFormatGS mFatSymbolProviderFormat = mSymbolProviderService.CreateFormatObj();
            MssSymbolGraphicGS mFatSymbolProviderGraphic = mSymbolProvider.CreateSymbolGraphic(mFatSymbolProviderString, mFatSymbolProviderFormat);
            mFatSymbolProviderGraphic.ExportToFile("C:\\icon");

Open in new window

0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Hello, well, I have an idea, I'm assuming that the error is raised at this line:
Type t_SymbolProvider = symbolProvider.GetType();

Open in new window


What if you try this instead, you need to know your COM GUID in Windows:
// Create a GUID object by passing the clsid parameter.
Guid myGuid1 = new Guid("1AE77DA4-1063-4ab3-BCD2-085B001EFB97");
// Get the type object associated with the CLSID.
Type t_SymbolProvider = Type.GetTypeFromCLSID(myGuid1);

Open in new window


Or maybe this, I unknown what is your COM ProgID, but here is an example of how to use it:
Type t_SymbolProvider = Type.GetTypeFromProgID("Microsoft.mshtml");

Open in new window


More info:
http://msdn.microsoft.com/en-us/library/980t1w1t.aspx
http://msdn.microsoft.com/en-us/library/hss5hw09.aspx

I hope this help.
0
 
thomasbau65Author Commented:
Hi
Well I have not tried it yet but following question pops up into my mind
if I go for the GUID or the GetTypeFromProgID I will be communicating directly with the COM object. If so I can a skip loading the assembly??
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Hello, looking at your code, what you say makes sense to me, try that.
0
 
thomasbau65Author Commented:
hi yv989c
we did it :-)
the trick was? call the correct class name! not the interface name....
thanks
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Good to know buddy!
0
 
thomasbau65Author Commented:
Well I was again to quick :-)
The code runs when called from the c# side

When called from the Java side

this is ok:

byte[] assemblyBytes = File.ReadAllBytes("C:\\MyDynamicAssembly.dll");
Assembly assembly = AppDomain.CurrentDomain.Load(assemblyBytes);

Open in new window



I can also display all the classes inside the dll like this

foreach (Type type in typeArray)
            {
                if (type.IsClass == true)
                {
                    Console.WriteLine("...Found Class : {0}", type.FullName);
                }
}

Open in new window


but adding:

object i_service = assembly.CreateInstance("Interop.MssComServer.MssSymbolProviderServiceGSClass");

Open in new window


will generate the same error as I had at the beginning

Any Idea??



0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
What is the error message?
0
 
thomasbau65Author Commented:
hi
here the message:

run:
...Found Class : Interop.MssComServer.MssSymbolProviderServiceGSClass
...Found Class : Interop.MssComServer.MssModifiersExGSClass
...Found Class : Interop.MssComServer.MssSymbolFormatGSClass
...Found Class : Interop.MssComServer.MssSymbolEditorGSClass
...Found Class : Interop.MssComServer.MssSymbolGraphicGSClass
...Found Class : Interop.MssComServer.MssSymbolNPointGraphicGSClass
...Found Class : Interop.MssComServer.MssDrawingItemGSClass
...Found Class : Interop.MssComServer.MssDrawingTargetGSClass
...Found Class : Interop.MssComServer.MssIconTileExporterGSClass
...Found Class : Interop.MssComServer.MssSymbolProviderGSClass
...Found Class : Interop.MssComServer.MssApp6aStringObjGSClass
...Found Class : Interop.MssComServer.MssSymbolHierarchyGSClass
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (0xe0434f4d), pid=2904, tid=5852
#
# JRE version: 6.0_23-b04
# Java VM: Java HotSpot(TM) Client VM (19.0-b09 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [KERNELBASE.dll+0xb727]
#
# An error report file with more information is saved as:
# C:\Users\tba\Documents\NetBeansProjects\APP6IconProvider\hs_err_pid2904.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

Open in new window


See also the jvm error log
  hs-err-pid2412.log
0
 
thomasbau65Author Commented:
Hi
Some time when one doesn't understand what's wrong and no more ideas are left, then the best is to restart your computer, unregister and reregister  the dll.
this did help...
again thanks for the support
th*
0
 
Carlos VillegasFull Stack .NET DeveloperCommented:
Glad to help buddy!
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 9
  • 9
Tackle projects and never again get stuck behind a technical roadblock.
Join Now