Есть некая нативная dll'ка, которая содержит функциональность, которая должна использоваться в Java приложении, но по некоторым соображениям ее нельзя переписать на Java. Назовем ее native.dll. Эта библиотека успешно используется в существующих C/C++ приложениях, но она ничего не знает о том, что она будет использоваться в Java приложении, т.е. она не экспортирует имена в удобном для Java виде. Предположим, она экспортирует функцию под именем DoSomething.
Для того, чтобы использовать native.dll, написан класс (с нативной реализацией в библиотеке adapter.dll)
package com.comp.adapter;
public class Adapter {
static {
System.loadLibrary("adapter");
}
public native void doSomething();
}
Это все дело работает, если запускается Java приложение, в текущей директории которого присутствуют обе библиотеки (native.dll и adapter.dll).
Это Java приложение деплоится через Java Web Start. Для этого обе нативные либы, упаковываются в native.jar, этот .jar подписывается и прописывается ссылка на него в .jnlp файл приложения.
Однако через Java Web Start это приложение не работает. В тот момент, когда приложение запускается, загружается (успешно) adapter.dll, выполняется вызов doSomething, пытается загрузиться библиотека native.dll, и она не находится. Почему не находится, в общем-то понятно -- вызов LoadLibrary ищет ее по "своим" местам: в директории экзешника (в данном случае %JRE_HOME%/bin), в текущей (десктоп текущего пользователя), в системной (C:\Windows\System32), в windows (C:\Windows), в директориях, указанных в %PATH%, но не там, куда ее скачал JWS.
Вопрос заключается в следующем: как сделать так, что бы native.dll находилась и загружалась, и могла быть использована?
Здравствуйте, dshe, Вы писали:
D>Вопрос заключается в следующем: как сделать так, что бы native.dll находилась и загружалась, и могла быть использована?
Такое ощущение, что это вообще не в яву.
А в этом си-коде можно вытащить содержимое jar ? Если да, то наверное можно это содержимое подсунуть в loadlibrary...
Спроси у сишников.
Здравствуйте, Cider, Вы писали:
C>Здравствуйте, dshe, Вы писали:
D>>Вопрос заключается в следующем: как сделать так, что бы native.dll находилась и загружалась, и могла быть использована?
C>А в этом си-коде можно вытащить содержимое jar ? Если да, то наверное можно это содержимое подсунуть в loadlibrary...
Ты имеешь ввиду распаковать? Думаю, можно. Было бы странно, если бы в нативном коде нельзя было бы сделать что-то, что можно в java. Проблема заключается в том, что я не знаю точно какой jar распаковывать (JWS сохраняет его не с оригинальным именем) и где он в файловой системе пользователя лежит.
--
Дмитро
Re: Нативные библиотеки и Java Web Start
От:
Аноним
Дата:
09.08.04 06:40
Оценка:
У меня такая же проблема. Т.е. в обыкновенном приложении dll подгружается и все работает, потом этот же код перевожу в вэб-приложение и вылетает вот такой эксэпшон:"java.lang.UnsatisfiedLinkError". Причем метод System.loadLibrary("xxxx") выполняется. А потом при вызове какого-либо метода все рушится.
И где найти ответ не знаю.
Елси ты разобрался, дай знать пожалуйста.
Спасибо.
D>Вопрос заключается в следующем: как сделать так, что бы native.dll находилась и загружалась, и могла быть использована?
Функция API LoadLibrary ищет библиотеки по следующим местам 1. Каталог, откуда было запущено приложение
2. Текущий каталог
3. Системный каталог
4. 16-битный системный каталог
5. Каталог Windows
6. Все каталоги из PATH
Следовательно, нужно всего лишь добавить нужный каталог в PATH. Либо можно в функции Java_com_comp_adapter_Adapter_doSomething использовать следующую функцию:
где dwFlags может, в частности, включать флаг LOAD_WITH_ALTERED_SEARCH_PATH. Если в lpFileName указан путь, то стратегия поиска меняется на 1. Каталог из lpFileName. Короче это каталог, где расположена библиотека
2. Текущий каталог
3. Системный каталог
4. 16-битный системный каталог
5. Каталог Windows
6. Каталог из PATH.
Возможно это то, что тебе нужно.
Здравствуйте, dshe, Вы писали:
D>Это Java приложение деплоится через Java Web Start. Для этого обе нативные либы, упаковываются в native.jar, этот .jar подписывается и прописывается ссылка на него в .jnlp файл приложения.
D>Вопрос заключается в следующем: как сделать так, что бы native.dll находилась и загружалась, и могла быть использована?
В jnlp файл native.jar добавлять следующим образом:
Друзья!! Да дело не в этом! У меня из обыкновенного приложения все грузится и работает.
А вот из вэб приложения, под резином — ничего. И нет у меня никаких xml файлов, я использую максимум web.xml, мне из моего класса надо подгрузитоь dll вsполнить несколько методов и все. И вроде сама dll находится и подгружается, а потом теряется, может дело в резине?
Оччень жду ответа, заранее бАльшое СПАСИБО
Здравствуйте, UnSmoke, Вы писали:
US>Друзья!! Да дело не в этом! У меня из обыкновенного приложения все грузится и работает. US>А вот из вэб приложения, под резином — ничего. И нет у меня никаких xml файлов, я использую максимум web.xml, мне из моего класса надо подгрузитоь dll вsполнить несколько методов и все. И вроде сама dll находится и подгружается, а потом теряется, может дело в резине? US>Оччень жду ответа, заранее бАльшое СПАСИБО
Здравствуйте, dfa, Вы писали:
dfa>>В твоем случае посмотри, что выдает
dfa>[skipped]
dfa>>Твои dll'ки должны лежать в указанном месте. Или можешь переопределить эту property.
dfa>Забыл сказать, что понятия не имею, будет ли это работать.
dfa>Так, на всякий случай.
dll-ки лежат по указанным путям. Все нормально. Но ничего не работает. Может все дело в явском обеспечении безопасности и переносимости? Может из-под вэб-приложения вообще нельзя dll-ки поднимать?
> dll-ки лежат по указанным путям. Все нормально. Но ничего не работает. Может все дело в явском обеспечении безопасности и переносимости? Может из-под вэб-приложения вообще нельзя dll-ки поднимать?
Need more details. www.caucho.com -> Search -> loadLibrary
если бы из-за безопасности, то был бы SecurityException...
Другие поднимают. Что пытаешься решить с помощью JNI?
Здравствуйте, Denis Afonin, Вы писали:
>> dll-ки лежат по указанным путям. Все нормально. Но ничего не работает. Может все дело в явском обеспечении безопасности и переносимости? Может из-под вэб-приложения вообще нельзя dll-ки поднимать?
DA>Need more details. www.caucho.com -> Search -> loadLibrary
DA>если бы из-за безопасности, то был бы SecurityException...
DA>Другие поднимают. Что пытаешься решить с помощью JNI?
Есть dll. Из обыкновенного приложения она поднимается и работает, т.е. вызываются методы и т.п.
Когда к этой же dll обращаюсь из сервлета или из другого класса, ничего не получается.
Т.е. метод System.loadLibrary("native");отрабатывает, а при обращении к к.л. методу из этой dll вылетает ошибка java.lang.UnsatisfiedLinkError. Вот.
А dll позволяет коннектится к MatLab. И работать с ним из Java программы. Моя задача сделать чтобы через вэб-интерфейс, можно было вызывать функции матлаба, и получать данные из него. Dll уже написана, не мной. Это JMatLink.
Т.е. есть ява-класс, который реализует поднимание этой dll-ки и обращение к ее методам.На сайте разработчика никакой поддержки — последнее обновление в 2001 году. Самое интересное то,что эта штука работает, и очень меня устраивает, но только в обыкновенном приложении. т.е. все отрабатывает — запускается матлаб, принимает запросы, считает там что-нибудь, и отдает ответ.
Может в резине какие нибудь настройки особые есть по этому поводу.
dll эту уже куда только не клал, и в системные пути чего только не добавлял, никакого результата.
Здравствуйте, UnSmoke, Вы писали:
US>Здравствуйте, Denis Afonin, Вы писали:
>>> dll-ки лежат по указанным путям. Все нормально. Но ничего не работает. Может все дело в явском обеспечении безопасности и переносимости? Может из-под вэб-приложения вообще нельзя dll-ки поднимать?
DA>>Need more details. www.caucho.com -> Search -> loadLibrary
DA>>если бы из-за безопасности, то был бы SecurityException...
DA>>Другие поднимают. Что пытаешься решить с помощью JNI?
US>Есть dll. Из обыкновенного приложения она поднимается и работает, т.е. вызываются методы и т.п.
Приложение Java или native? US>Когда к этой же dll обращаюсь из сервлета или из другого класса, ничего не получается.
А то если Java, то не вполне понятно, почему "из другого класса ничего не получается" US>Т.е. метод System.loadLibrary("native");отрабатывает, а при обращении к к.л. методу из этой dll вылетает ошибка java.lang.UnsatisfiedLinkError. Вот.
Есть у меня резонное ощущение, что ты пытаешься напрямую вызвать DLL из Java путем простой декларации native-метода без описания его реализации.
Дай пожалуйста пример кода и stack trace ошибки на этом коде.
Re[9]: Нативные библиотеки и Java Web Start
От:
Аноним
Дата:
10.08.04 09:27
Оценка:
Здравствуйте, nant, Вы писали:
N>Приложение Java или native?
Приложение вот такое
public class Test {
public static void main(String args[]) {
JMatLink engine=new JMatLink();
engine.engOpenSingleUse();
engine.engEvalString("m=2");
engine.engClose();
}
}
JMatLink — это класс, который обращается к dll. Т.е. он и вызывает System.loadLibrary("JMatLink"), и остальные методы.
Вот он
import java.io.*;
public class JMatLink extends Thread {
// static declarations
// the variable "status" is used to tell the main
// thread what to do.private final static int idleI = 0;
private final static int engOpenI = 1;
private final static int engCloseI = 2;
private final static int engEvalStringI = 3;
private final static int engGetScalarI = 4;
private final static int engGetVectorI = 5;
private final static int engGetArrayI = 6;
private final static int engPutArray2dI = 9;
private final static int engOutputBufferI = 10;
private final static int engGetCharArrayI = 11;
private final static int destroyJMatLinkI = 12;
private final static int engOpenSingleUseI = 13;
// All variables are global to allow all methods
// and the main thread to share all dataprivate int status = idleI;
private String arrayS;
private String engEvalStringS;
private String engOutputBufferS;
private double engGetScalarD;
private double[] engGetVectorD;
private double[][] engGetArrayD;
private double engPutArrayD;
private double[] engPutArray1dD;
private double[][] engPutArray2dD;
private String[] engGetCharArrayS;
private int epI; /* Engine pointer */private int retValI; /* return Value of eng-methods */private String startCmdS; /* start command for engOpen... */private int buflenI; /* output buffer length */private boolean debugB = false;
// Locksprivate boolean lockEngineB = false;
private boolean lockThreadB = false;
private boolean lockWaitForValueB = false;
private boolean destroyJMatLinkB = false;
private Thread runner;
// *********************** native declarations ****************************
// NEVER call native methods directly, like
// JMatLink.engEvalStringNATIVE("a=1"). Matlab's engine has quite some
// thread problems. private native void displayHelloWorld();
private native void engTestNATIVE();
private native int engOpenNATIVE (String startCmdS );
private native int engOpenSingleUseNATIVE (String startCmdS );
private native int engCloseNATIVE (int epI);
private native int engEvalStringNATIVE (int epI, String evalS );
private native double engGetScalarNATIVE (int epI, String nameS );
private native double[] engGetVectorNATIVE (int epI, String nameS );
private native double[][] engGetArrayNATIVE (int epI, String nameS );
private native String[] engGetCharArrayNATIVE (int epI, String nameS );
private native void engPutArrayNATIVE (int epI, String matrixS, double[][] valuesDD);
private native String engOutputBufferNATIVE (int epI, int buflenI );
private native void setDebugNATIVE (boolean debugB );
// *******************************************************************************
// ************** load JMatLink library into memory **********************static {
try { //System.out.println("loading");
System.loadLibrary("JMatLink");
//System.out.println("loaded");
}
catch (UnsatisfiedLinkError e) {
System.out.println("ERROR: Could not load the JMatLink library");
System.out.println(" This error occures, if the path to");
System.out.println(" matlab's <matlab>\\bin directory is");
System.out.println(" not set properly.");
System.out.println(" Or if JMatLink.dll is not found.");
}
}
// ************************ JMatLink constructor ***************************
/** This is the constructor for the JMatLink library.
*
* <p>E.g.:<br>
* <pre>
* <b>JMatLink</b> engine = new <b>JMatLink()</b>;
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/public JMatLink() {
if (debugB) System.out.println("JMatLink constructor");
runner = new Thread(this);
runner.start();
}
// **** terminate running thread ****public void destroy() {
destroyJMatLinkB = true;
notifyAll();
}
public void kill() {
destroyJMatLinkB = true;
callThread(destroyJMatLinkI);
}
//////////////////////////////////////////////////////////////////////////////
// ***************************** engOpen *****************************
/** Open engine. This command is used to open a <b>single</b> connection
* to matlab.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.<b>engOpen()</b>;
* engine.engEvalString("surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized int engOpen()
{
return engOpen( "" ); // return value is pointer to engine
}
// ***************************** engOpen *******************************
/** Open engine. This command is used to open a <b>single</b> connection
* to matlab.<p> This command is only useful on unix systems. On windows
* the optional parameter <b>must</b> be NULL.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.<b>engOpen("commands to start matlab")</b>;
* engine.engEvalString("surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized int engOpen(String startCmdS)
{
// startup MATLAB and set up connection
lockEngineLock();
lockWaitForValue();
this.startCmdS = startCmdS;
callThread( engOpenI );
WaitForValue();
releaseEngineLock();
return this.epI;
}
// ************************** engOpenSingleUse *****************************
/** Open engine for single use. This command is used to open
* <b>multiple</b> connections to matlab.
*
* <p>E.g.:<br>
* <pre>
* int a,b;
* JMatLink engine = new JMatLink();
* a = engine.<b>engOpenSingleUse()</b>; // start first matlab session
* b = engine.<b>engOpenSingleUse()</b>; // start second matlab session
* engine.engEvalString(a, "surf(peaks)");
* engine.engEvalString(b, "foo=ones(10,0)");
* engine.engClose(a);
* engine.engClose(b);
* </pre>
***************************************************************************/public synchronized int engOpenSingleUse()
{
return engOpenSingleUse("");
}
// ************************** engOpenSingleUse *****************************
/** Open engine for single use. This command is used to open
* <b>multiple</b> connections to matlab.
*
* <p>E.g.:<br>
* <pre>
* int a,b;
* JMatLink engine = new JMatLink();
* a = engine.<b>engOpenSingleUse("start matlab")</b>; // start first matlab session
* b = engine.<b>engOpenSingleUse("start matlab")</b>; // start second matlab session
* engine.engEvalString(a, "surf(peaks)");
* engine.engEvalString(b, "foo=ones(10,0)");
* engine.engClose(a);
* engine.engClose(b);
* </pre>
***************************************************************************/public synchronized int engOpenSingleUse(String startCmdS)
{
lockEngineLock();
lockWaitForValue();
this.startCmdS = startCmdS;
callThread( engOpenSingleUseI );
WaitForValue();
releaseEngineLock();
return this.epI;
}
// ***************************** engClose *****************************
/** Close the connection to matlab.
*
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* engine.<b>engClose()</b>;
* </pre>
***************************************************************************/public synchronized void engClose()
{
engClose( this.epI );
}
// ***************************** engClose *****************************
/** Close a specified connection to an instance of matlab.
*
* <p>E.g.:<br>
* <pre>
* int a,b;
* JMatLink engine = new JMatLink();
* a = engine.engOpenSingleUse(); // start first matlab session
* b = engine.engOpenSingleUse(); // start second matlab session
* engine.engEvalString(b, "surf(peaks)");
* engine.engEvalString(a, "array = randn(23)");
* engine.<b>engClose</b>(a); // Close the first connection to matlab
* engine.<b>engClose</b>(b); // Close the second connection to matlab
* </pre>
***************************************************************************/public synchronized void engClose( int epI)
{
// close connection and terminate MATLAB
lockEngineLock();
lockWaitForValue();
this.epI = epI;
callThread( engCloseI );
WaitForValue();
releaseEngineLock();
// return retValI; Return value indicates success
}
// ***************************** engEvalString *****************************
/** Evaluate an expression in matlab's workspace.
*
* E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engEvalString</b>("surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized void engEvalString(String evalS)
{
engEvalString( this.epI, evalS);
}
// ***************************** engEvalString *************************
/** Evaluate an expression in a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* int a,b;
* JMatLink engine = new JMatLink();
* a = engine.engOpenSingleUse();
* engine.<b>engEvalString</b>(a, "surf(peaks)");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized void engEvalString(int epI, String evalS)
{
// evaluate expression "evalS" in specified engine Epif (debugB) System.out.println("eval(ep,String) in " + epI + " "+evalS);
lockEngineLock();
lockWaitForValue();
this.epI = epI;
engEvalStringS = evalS;
callThread( engEvalStringI );
WaitForValue();
releaseEngineLock();
if (debugB) System.out.println("eval(ep,String) out "+epI+" "+evalS);
// return retValI; Return value indicates success
}
// ***************************** engGetScalar **************************
/** Get a scalar value from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double a;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("foo = sin( 3 )");
* a = engine.<b>engGetScalarValue</b>("foo");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized double engGetScalar(String arrayS)
{
return engGetScalar( this.epI, arrayS);
}
// ***************************** engGetScalar **************************
/** Get a scalar value from a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* double a;
* int b;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSigleUse();
* engine.engEvalString(b, "foo = sin( 3 )");
* a = engine.<b>engGetScalarValue</b>(b, "foo");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized double engGetScalar(int epI, String arrayS)
{
// Get scalar value or element (1,1) of an array from
// MATLAB's workspace
// Only real values are supported right now
lockEngineLock();
lockWaitForValue();
/* copy parameters to global variables */this.epI = epI;
this.arrayS = arrayS;
callThread( engGetScalarI );
WaitForValue();
releaseEngineLock();
return engGetScalarD;
}
// ***************************** engGetVector **************************
/** Get an array (1 * n) from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double[] array;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("array = randn(10,1);");
* array = engine.<b>engGetVector</b>("array");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized double[] engGetVector( String arrayS )
{
return engGetVector( this.epI, arrayS );
}
// ***************************** engGetVector **************************
/** Get an array (1 * n) from a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* int b;
* double[] array;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.engEvalString(b, "array = randn(10,1);");
* array = engine.<b>engGetVector</b>(b, "array");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized double[] engGetVector( int epI, String arrayS )
{
// only real values are supported so far
lockEngineLock();
lockWaitForValue();
this.epI = epI;
this.arrayS = arrayS;
callThread( engGetVectorI );
WaitForValue();
releaseEngineLock();
return engGetVectorD;
}
// ***************************** engGetArray ***************************
/** Get an array from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* int b;
* double[][] array;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("array = randn(10);");
* array = engine.<b>engGetArray</b>("array");
* engine.engClose();
* </pre>
***************************************************************************/public synchronized double[][] engGetArray( String arrayS )
{
return engGetArray( this.epI, arrayS );
}
// ***************************** engGetArray ***************************
/** Get an array from a specified instance/workspace of matlab.
*
* <p>E.g.:<br>
* <pre>
* int b;
* double[][] array;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.engEvalString(b, "array = randn(10);");
* array = engine.<b>engGetArray</b>(b, "array");
* engine.engClose(b);
* </pre>
***************************************************************************/public synchronized double[][] engGetArray( int epI, String arrayS )
{
// only real values are supported so far
lockEngineLock();
lockWaitForValue();
this.epI = epI;
this.arrayS = arrayS;
callThread( engGetArrayI );
WaitForValue();
releaseEngineLock();
return engGetArrayD;
}
// ************************** engGetCharArray *****************************
/** Get an 'char' array (string) from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* String array;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("array = 'hello world';");
* array = engine.<b>engCharArray</b>("array");
* System.out.println("output = "+ array);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized String[] engGetCharArray(String arrayS)
{
// convert to double array
engEvalString( "engGetCharArrayD=double(" + arrayS +")" );
// get double arraydouble[][] arrayD = engGetArray("engGetCharArrayD");
// delete temporary double array
engEvalString("clear engGetCharArrayD");
// convert double back to charreturn double2String( arrayD );
}
// ***************************** engPutArray ***************************
/** Put an array into a specified workspace.
*
* <p>E.g.:<br>
* <pre>
* int array = 1;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized void engPutArray( String arrayS, int valueI )
{
engPutArray( this.epI, arrayS, new Integer(valueI).doubleValue());
}
// ***************************** engPutArray ***************************
// public synchronized void engPutArray( String arrayS, int[] valuesI )
// {
// engPutArray( this.epI, arrayS, (double[])valuesI );
// }
// ***************************** engPutArray ***************************
/** Put an array into matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double array = 1;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized void engPutArray( String arrayS, double valueD )
{
engPutArray( this.epI, arrayS, valueD);
}
// ***************************** engPutArray *****************************
/** Put an array into a specified instance/workspace of matlab.
*
* <p>E.g.:<br>
* <pre>
* int b;
* double array = 1;
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.<b>engPutArray</b>(b, "array", array);
* engine.engClose(b);
* </pre>
***************************************************************************/public synchronized void engPutArray( int epI, String arrayS, double valueD )
{
double vDD[][] = {{0.0}};
vDD[0][0] = valueD;
engPutArray( epI, arrayS, vDD ); // nxn dimensional
}
// ***************************** engPutArray ***************************
/** Put an array (1 dimensional) into a specified instance/workspace of
* matlab.
*
* <p>E.g.:<br>
* <pre>
* double[] array = {1.0 , 2.0 , 3.0};
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized void engPutArray( String arrayS, double[] valuesD )
{
engPutArray( this.epI, arrayS, valuesD );
}
// ***************************** engPutArray *****************************
/** Put an array (1 dimensional) into a specified instance/workspace of
* matlab.
*
* <p>E.g.:<br>
* <pre>
* int b;
* double[] array = {1.0 , 2.0 , 3.0};
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.<b>engPutArray</b>(b, "array", array);
* engine.engClose(b);
* </pre>
***************************************************************************/public synchronized void engPutArray(int epI, String arrayS, double[] valuesD)
{
double[][] vDD = new double[1][valuesD.length]; // 1xn arrayif (debugB) System.out.println("length = "+valuesD.length);
vDD[0] = valuesD; // copy row
engPutArray( epI, arrayS, vDD );
}
// ***************************** engPutArray ***************************
/** Put an array (2 dimensional) into matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* double[][] array={{1.0 , 2.0 , 3.0},
* {4.0 , 5.0 , 6.0}};
* JMatLink engine = new JMatLink();
* engine.engOpenSingleUse();
* engine.<b>engPutArray</b>("array", array);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized void engPutArray( String arrayS, double[][] valuesDD )
{
engPutArray( this.epI, arrayS, valuesDD );
}
// ***************************** engPutArray ***************************
/** Put an array (2 dimensional) into a specified instance/workspace of
* matlab.
*
* <p>E.g.:<br>
* <pre>
* int b;
* double[][] array={{1.0 , 2.0 , 3.0},
* {4.0 , 5.0 , 6.0}};
* JMatLink engine = new JMatLink();
* b = engine.engOpenSingleUse();
* engine.engPutArray(b, "array", array);
* engine.engClose(b);
* </pre>
***************************************************************************/public synchronized void engPutArray(int epI, String arrayS, double[][] valuesDD)
{
// send an array to MATLAB
// only real values are supported so far
lockEngineLock();
lockWaitForValue();
this.epI = epI;
this.arrayS = arrayS;
this.engPutArray2dD = valuesDD;
callThread( engPutArray2dI );
WaitForValue();
releaseEngineLock();
}
// ***************************** engOutputBuffer ***********************
/** Return the outputs of previous commands from matlab's workspace.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* buffer = engine.<b>engOutputBuffer</b>();
* System.out.println("workspace " + buffer);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized String engOutputBuffer( )
{
return engOutputBuffer( this.epI, this.buflenI );
}
// ***************************** engOutputBuffer ***********************
/** Return the outputs of previous commands from a specified instance/
* workspace form matlab.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* buffer = engine.<b>engOutputBuffer</b>();
* System.out.println("workspace " + buffer);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized String engOutputBuffer( int epI )
{
return engOutputBuffer( epI, this.buflenI );
}
// ***************************** engOutputBuffer ***********************
/** Return the ouputs of previous commands in matlab's workspace.
*
* Right now the parameter <i>buflen</i> is not supported.
*
* <p>E.g.:<br>
* <pre>
* String buffer;
* JMatLink engine = new JMatLink();
* engine.engOpen();
* engine.engEvalString("surf(peaks)");
* buffer = engine.<b>engOutputBuffer</b>();
* System.out.println("workspace " + buffer);
* engine.engClose();
* </pre>
***************************************************************************/public synchronized String engOutputBuffer( int epI, int buflenI )
{
// get the output buffer from MATLABif (debugB) System.out.println("Thread in: "+Thread.currentThread().getName());
lockEngineLock();
lockWaitForValue();
this.epI = epI;
this.buflenI = buflenI;
callThread( engOutputBufferI );
WaitForValue();
releaseEngineLock();
if (debugB) System.out.println("Thread out: "+Thread.currentThread().getName());
return engOutputBufferS;
}
// ***************************** setDebug *******************************
/* Switch on or disable debug information printed to standard output.
*
* <p>Default setting is debug info disabled.
* <p>E.g.:<br>
* <pre>
* JMatLink engine = new JMatLink();
* engine.engOpenSingleUse();
* engine.<b>setDebug(true)</b>;
* engine.engEvalString("a=ones(10,5);");
* engine.engClose();
* </pre>
***************************************************************************/public void setDebug( boolean debugB )
{
this.debugB = debugB;
setDebugNATIVE( debugB );
}
////////////////////////////////////////////////////////////////////////////////
// This method notifys the main thread to call matlab's engine
// Since threads don't have methods, we set a variable which
// contains the necessary information about what to do.private synchronized void callThread(int status)
{
this.status = status;
lockThreadB = false;
notifyAll();
}
////////////////////////////////////////////////////////////////////////////////
// The run methods does ALL calls to the native methods
// The keyword "synchronized" is neccessary to block the run()
// method as long as one command needs to get executed.public synchronized void run()
{
int tempRetVal;
if (debugB) System.out.println("JMatLink: thread is running");
while (true) {
// System.out.println("Number of Java-Threads: "+Thread.activeCount()+"");
// Thread thread = Thread.currentThread();
// System.out.println("Name of active Java-Threads: "+thread.getName()+"");
// System.out.println("active Java-Thread is Daemon: "+thread.isDaemon();+""); switch (status) {
case engOpenI: epI = engOpenNATIVE( startCmdS );
releaseWaitForValue();
break;
case engOpenSingleUseI: epI = engOpenSingleUseNATIVE( startCmdS );
releaseWaitForValue();
break;
case engCloseI: retValI = engCloseNATIVE( epI );
releaseWaitForValue();
break;
case engEvalStringI: retValI = engEvalStringNATIVE(epI, engEvalStringS);
releaseWaitForValue();
break;
case engGetScalarI: engGetScalarD = engGetScalarNATIVE(epI, arrayS );
releaseWaitForValue();
break;
case engGetVectorI: engGetVectorD = engGetVectorNATIVE(epI, arrayS );
releaseWaitForValue();
break;
case engGetArrayI: engGetArrayD = engGetArrayNATIVE(epI, arrayS );
releaseWaitForValue();
break;
case engGetCharArrayI: engGetCharArrayS = engGetCharArrayNATIVE(epI, arrayS );
releaseWaitForValue();
break;
case engPutArray2dI: engPutArrayNATIVE( epI, arrayS, engPutArray2dD );
releaseWaitForValue();
break;
case engOutputBufferI: engOutputBufferS = engOutputBufferNATIVE( epI, buflenI );
releaseWaitForValue();
break;
default: //System.out.println("thread default switch statem.");
}
status=0;
lockThreadB = true;
while (lockThreadB == true) {
synchronized(this) {
try { wait();} // wait until next command is availablecatch (InterruptedException e) { }
}
}
//System.out.println("JMatLink: thread awoke and passed lock"); if (destroyJMatLinkB == true) break;
} // end whileif (debugB) System.out.println("JMatLink: thread terminated");
} // end run
////////////////////////////////////////////////////////////////////////////////
// The MATLAB engine is served by a thread. Threads don't have methods
// which can be called. So we need to send messages to that thread
// by using notifyAll. In the meantime NO OTHER methods is allowed to
// access our thread (engine) so we lock everything up. private void lockEngineLock(){
synchronized(this){
while (lockEngineB==true){
try { //System.out.println("lockEngineLock locked");
wait();} // wait until last command is finishedcatch (InterruptedException e) { }
}
//now lockEngineB is false
lockEngineB = true;
}
} // end lockEngineprivate synchronized void releaseEngineLock(){
lockEngineB = false;
notifyAll();
}
////////////////////////////////////////////////////////////////////////////////
// The MATLAB engine is served by a thread. Threads don't have methods
// which can be called directly. If we send a command that returns data
// back to the calling function e.g. engGetArray("array"), we'll notify
// the main thread to get the data from matlab. Since the data is collected
// in another thread, we don't know exactly when the data is available, since
// this is a concurrent situation.
// The solution is simple: I always use a locking-mechanism to wait for the
// data. The main thread will release the lock and the calling method can
// return the data.
//
// Steps:
// 1. a method that returns data calls the locking method
// 2. notify the thread to call matlab
// 3. wait for the returned data
// 4. after the thread itself got the data it releases the locks method
// 5. return dataprivate synchronized void lockWaitForValue(){
lockWaitForValueB = true;
}
private void WaitForValue(){
synchronized(this){
while (lockWaitForValueB==true){
try { //System.out.println("lockWaitForValue locked");
wait();} // wait for return valuecatch (InterruptedException e) { }
}
}
//System.out.println("WaitForValue released");
} // end waitForValueprivate synchronized void releaseWaitForValue(){
lockWaitForValueB = false;
notifyAll();
}
////////////////////////////////////////////////////////////////////////////////
//// Utility methods ////
// Convert an n*n double array to n*1 String vectorprivate String[] double2String(double[][] d)
{
String encodeS[]=new String[d.length]; // String vector
// for all rowsfor (int n=0; n<d.length; n++){
byte b[] = new byte[d[n].length];
// convert row from double to bytefor (int i=0; i<d[n].length ;i++) b[i]=(byte)d[n][i];
// convert byte to Stringtry { encodeS[n] = new String(b, "UTF8");}
catch (UnsupportedEncodingException e) {}
}
return encodeS;
} // end double2String
} // end class JMatLink
N>А то если Java, то не вполне понятно, почему "из другого класса ничего не получается" N>Есть у меня резонное ощущение, что ты пытаешься напрямую вызвать DLL из Java путем простой декларации native-метода без описания его реализации.
N>Дай пожалуйста пример кода и stack trace ошибки на этом коде.
java.lang.UnsatisfiedLinkError: engOpenSingleUseNATIVE
at beans.JMatLink.engOpenSingleUseNATIVE(Native Method)
at beans.JMatLink.run(JMatLink.java:867)
at java.lang.Thread.run(Thread.java:534)
причем если я создаю какой-нить класс, и делаю в нем метод который вызывает эти ф-ии, а потм в сервлете создаю объект этого класса и вызываю этот метод — та же история
That's a JDK "feature". You can't load a JNI library in more than one
classloader. That means if you try to load the .dll (or .so) with the
web-app loader, and then the application restarts (because you touched
the resin.conf or a .jar or a .class) the reloaded application will then
fail when it tries to load the JNI.
The easiest way to work around that is to put the class with the
System.loadLibrary in the global classpath, i.e. resin/lib, instead of
in WEB-INF/lib.