dukeify / fake-jni Goto Github PK
View Code? Open in Web Editor NEWAn implementation of the JNI and JVMTI with support for direct interaction between natively registered classes and JVM objects.
License: Other
An implementation of the JNI and JVMTI with support for direct interaction between natively registered classes and JVM objects.
License: Other
The code base is pretty polluted with generalized templates that are not necessarily specific to fake-jni. We should move all non-essential templates to the CX template library, to declutter the project and for code reuse in the future.
Since f072e5c, internal fake-jni base types do not require the use of CX::ExplicitCastGenerator
to define explicit casting routes for multiple inheritance types.
fake-jni has grown too large to be a header-only library; compile times are taking much longer than a standard shared library, the header include dependency ordering is too complex to easily make changes to, and the user API is suffering from unclear multiple definition compile-time errors when incorrectly including fake-jni, due to the inline functions and members as part of the library. Furthermore, the startup time and memory complexity of fake-jni, as a header-only library, grows linearly with every translation unit that it is included in, once again, due to the statically allocated inline members and inline functions.
Transitioning to a standard shared library model will solve all of these issues as all statically allocated memory and inline functions will only be defined in a single translation unit, regardless of the include count.
FakeJni::_CX::RegistrationHookGenerator
is an unnecessary template that can be replaced with capturing lambdas at each constructor for FakeJni::_CX::ClassDescriptorElement
. This issue is waiting on #22.
From the JVMTI spec:
An agent L that is statically linked will prohibit an agent of the same name from being loaded dynamically.
Since the type width of char
does not equal that of JChar
, JCharArray::length
does not represent the actual length of the string, but rather the length of the string / sizeof(JChar)
, excluding the null-terminator. Just add a field and API function to JString for the actual string size.
JNI:
Internal API:
Just to keep code neat, would simplify
vm.attachLibrary("./myLibrary.so", "", {&dlopen, &dlsym, &dlclose});
to
vm.attachLibrary("./myLibrary.so", "");
When defining an inner class, the first parameter for each constructor must be an instance pointer to the encapsulating class:
using namespace FakeJni;
class Outer : public JObject {
public:
DEFINE_CLASS_NAME("com/example/Outer")
class Inner : public JObject {
public:
DEFINE_CLASS_NAME("com/example/Outer$Inner")
const Outer& outer;
explicit Inner(Outer * const inst) :
outer(*inst)
{}
};
};
BEGIN_NATIVE_DESCRIPTOR(Outer)
{Constructor<Outer> {}}
END_NATIVE_DESCRIPTOR
BEGIN_NATIVE_DESCRIPTOR(Outer::Inner)
{Constructor<Outer::Inner, Outer *> {}}
END_NATIVE_DESCRIPTOR
For the purposes of JVM functionality compliance, all Outer::Inner
instances will be constrained to an encapsulating instance of Outer
.
Member functions marked with const
are being handled by the member field constructor in class.h
Required for the implementation of JNI exception functions.
Allow for parallel reads but block on parallel insertion for all class member descriptors and jvm properties
libffi
build script into its own .cmake
filelibffi
, use that if it exists, otherwise compile libffi
and link it statically (additionally allow the ability to override this to force static compilation)Right now registered fields must be encapsulated by an object that is derived from FakeJni::JObject
, methods however, have no such restriction. This is arbitrary and should be removed.
fake-jni requires clang, c++17 and CMake 3.8. One or more of these requirements is breaking the CircleCI builds
Right now fake-jni/library.h
uses the suffix of the requested library to determine the JNI and Agent linkage types (either static or dynamic), however, this is not JVM compliant. There is a predefined detection and loading order for both JNI and Agent libraries.
Right now the conversion operators for all JNI classes allow union_cast
ing to their fake-jni
equivalents, however they do not explicit disallow dereferencing without conversion. This behaviour should be disallowed to prevent UB.
Use sfinae templates to automatically promote any integral types smaller than int
to int
, and likewise for double
, to generate template class encapsulated functions for _CX::getVArg
.
Similar to the exhaustive signature checking for virtual member method dispatch. Derived native objects do not need to declare a field from their base class in order for it to be accessible through the JNI. This applies to, retrieval, modification and lookup functions.
FakeJni::JClass
and the rest of the internal pre-defined fake-jni native types aren't currently added to any FakeJni::DefaultJvm
instances automatically, thus they should never be removed. Also, the FakeJni::JClass
descriptor seems to be removed no matter what template parameter is passed to FakeJni::JvmImpl::unregisterClass<T>()
. See #18
Something along the lines of DEFINE_COMPLEX_CLASS(name, bases...)
that expands to:
class name: (public bases...), public virtual NativeObject<name>
and may be used like:
class MyBaseObject: public NativeObject<MyBaseObject> {
public:
const JString someProperty;
MyBaseObject(JString someProperty) :
NativeObject<MyBaseObject>(),
someProperty(someProperty)
{}
JInt myExampleFunction() {
return 31415926;
}
};
//Constructor delegate for MyBaseObject
static MyBaseObject* myBaseObjectConstructorDelegate(JString *str) {
return new MyBaseObject(*str);
}
//Register properties from MyBaseObject
DEFINE_NATIVE_TYPE(MyBaseObject) {
{&MyBaseObject::someProperty, "myJavaPropertyName"},
{&MyBaseObject::myExampleFunction, "myJavaFunctionName"},
{myBaseObjectConstructorDelegate}
};
//Define complex class that inherits all registered properties from it's base classes,
//with the exception of constructors
DEFINE_COMPLEX_CLASS(MyDerivedObject, MyBaseObject) {
public:
const JInt someOtherProperty;
MyDerivedObject(JInt someOtherProperty) :
NativeObject<MyDerivedObject>(),
MyBaseObject({ "I'm a JString!" }),
someOtherProperty(someOtherProperty)
{}
};
//Constructor delegate for MyDerivedObject
static MyDerivedObject* myDerivedObjectConstructorDelegate(JInt i) {
return new MyDerivedObject(i);
}
DEFINE_NATIVE_TYPE(MyDerivedObject) {
{&MyDerivedObject::someOtherProperty, "someOtherProperty"},
{myDerivedObjectConstructorDelegate}
};
Provide static assertions for overlapping fields from non-virtual bases
Related to #8
Currently FakeJni::NativeObject<typename>
only defines a JObject* newInstance(va_list)
function for creating new instances of user-defined native classes, with c-varargs. We eventually need to add support for a JObject* newInstance(jvalue*)
function that can create instances given jvalue[]
s. FakeJni::JMethodID
already defines an invoke function for jvalue
s so no new functionality is required to achieve this.
Currently there is no planned functionality for lifetime modifiers, however, in the future access checks and may need to be implemented.
The access modifiers are outlined in the JVM specification chapter 4:
Ensure that CallStaticXMethod
is not invoked for a non-static method descriptor and vice versa.
When registerNatives
is invoked, preform a depth-first search for the corresponding function in all libraries registered with the JVM instance. The first symbol found will be registered in place of the function pointer provided by the JNINativeMethod
struct.
Constructor delegate functions can be removed in favour of direct instantiation through the supplied template parameter to FakeJni::NativeObject
, however, we need to settle on a syntax for the registration. Since a delegate function wont be used for template parameter inference anymore, users must explicitly specify the template parameters for the prototype of the constructor somehow. This cannot be achieved with implicit conversions if no parameter is used to perform type inference on. Perhaps an empty template type could be used to minimize the impact on the end-user API bloat, something like:
template<typename... Args>
class Constructor {
public:
const uint32_t modifiers;
Constructor(const uint32_t modifiers): modifiers(modifiers) {}
};
with the resulting registration looking something like:
DEFINE_NATIVE_TYPE(MyNativeType) {
{&MyNativeType::someProperty, "someProperty"},
Constructor<JString*, JInt, JDoubleArray*>{},
Constructor<>{ JMethodID::PRIVATE }
};
Classes like JClass
, JMethodID
and JFieldID
should be extensible. Add functionality to use the user-defined derivations at a Jvm level. Globally, everything will still use the bases to remain binary compatible.
The current implementation of FakeJni::JString::JString(const JString&)
constructs a new FakeJni::JCharArray
instance and copies the contents of the subject string into the current string. Instead, we should simply set the array pointer in FakeJni::JArray<JCharArray>
to that of the allocated string.
To prevent undefined behaviour, should the underlying string be a stack-allocated reference, a constructor would need to be added to FakeJni::JArray<T>
that ref counts so that the last instance deallocates the subject memory when destructed.
This issue is related to #29.
See CallNonvirtualObjectMethod
vs CallObjectMethod
.
An implementation of this functionality would probably only require that we look at the descriptors of base classes for inherited functions. We would need to check that the base class' function is declared virtual to ensure that invoking that function on a derived object ptr/ref would not be undefined.
fake-jni
Right now they're just randomly generated strings
fake-jni/invoke/invoke.h
and fake-jni/native/native_constructor.h
can be cleaned up to match fake-jni/jvmti/interface_constructor.h
, decreasing code bloat.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.