aboutsummaryrefslogtreecommitdiff
path: root/libjava/gnu/gcj/runtime/natSharedLibLoader.cc
blob: 49bcfb4d10fca828431f5870c6ec8ede03fe178f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// natSharedLibLoader.cc - Implementation of FirstThread native methods.

/* Copyright (C) 2001, 2003  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

#include <config.h>

#include <gcj/cni.h>
#include <gnu/gcj/runtime/SharedLibLoader.h>
#include <java/io/IOException.h>
#include <java/lang/UnsupportedOperationException.h>
#include <java/lang/UnsatisfiedLinkError.h>

#ifdef HAVE_DLOPEN
#include <dlfcn.h>

/* Only used during dlopen, while having a lock on Class.class. */
static gnu::gcj::runtime::SharedLibLoader* curLoader;

typedef void (*ClassHookFunc) (jclass);

static void
::register_hook(jclass cls)
{
  curLoader->registerClass(cls->getName(), cls);
}

struct SharedLibDummy
{
  ClassHookFunc saved;
  SharedLibDummy()
  {
    saved = _Jv_RegisterClassHook;
  }
  ~SharedLibDummy()
  {
    _Jv_RegisterClassHook = saved;
    curLoader = NULL;
  }
};
#endif

void
gnu::gcj::runtime::SharedLibLoader::init(jstring libname, jint flags)
{
#ifdef HAVE_DLOPEN
  jint len = _Jv_GetStringUTFLength (libname);
  char lname[len + 1];
  JvGetStringUTFRegion (libname, 0, libname->length(), lname);
  lname[len] = '\0';

  if (flags==0)
    flags = RTLD_LAZY;
  JvSynchronize dummy1(&java::lang::Class::class$);
  SharedLibDummy dummy2;
  curLoader = this;
  _Jv_RegisterClassHook = ::register_hook;
  void *h = dlopen(lname, flags);
  if (h == NULL)
    {
      const char *msg = dlerror();
      jstring str = JvNewStringLatin1 (lname);
      str = str->concat (JvNewStringLatin1 (": "));
      str = str->concat (JvNewStringLatin1 (msg));
      throw new java::lang::UnsatisfiedLinkError (str);
    }
  handler = (gnu::gcj::RawData*) h;
#else
  const char *msg = "SharedLibLoader is not supported on this platform";
  throw new java::lang::UnsupportedOperationException(JvNewStringLatin1(msg));
#endif
}

void
gnu::gcj::runtime::SharedLibLoader::finalize()
{
#ifdef HAVE_DLOPEN
  dlclose (handler);
#endif
}