Abstract

The Internet of medical things (IoMT) has become a promising paradigm, where the invaluable additional data can be collected by the ordinary medical devices when connecting to the Internet. The deep understanding of symptoms and trends can be provided to patients to manage their lives and treatments. However, due to the diversity of medical devices in IoMT, the codes of healthcare applications may be manipulated and tangled by malicious devices. In addition, the linguistic structures for layer activation in languages cause controls of layer activation to be part of program’s business logic, which hinders the dynamic replacement of layers. Therefore, to solve the above critical problems in IoMT, in this paper, a new approach is firstly proposed to support the dynamic replacement of layer in IoMT applications by incorporating object proxy into virtual machine (VM). Secondly, the heap and address are used to model the object and object evolution to guarantee the feasibility of the approach. After that, we analyze the influences of field access and method invocation and evaluate the risk and safety of the application when these constraints are satisfied. Finally, we conduct the evaluations by extending Java VM to validate the effectiveness of the proposal.

1. Introduction

Internet of medical things (IoMT), which plays an important role in healthcare industry to construct the safety and healthy system in human society [1], is becoming the critical part in reducing healthcare costs, providing timely medical responses, and increasing the quality of medical treatment. IoMT, in fact, is an ecosystem of connected different kinds of sensors, including the wearable devices, medical devices, and clinical systems. Each part in the ecosystem has its own particular context, which is different from others. On one hand, various contexts should be managed by the healthcare application to provide context-based services. For example, to avoid patients’ information leakage, a function component of a healthcare application is used to describe the medical histories of patients to doctor in detail, instead of collecting the sensitive information. On the other hand, the component can be applied in smart watches to regulate the patients’ personal information. However, due to crosscut, the codes are easily scattered and tangled by context, which increase the costs of healthcare applications’ development and maintenance.

Recently, some researchers have introduced the technologies from academic and industry to improve the effectiveness and performance of IoMT applications. For example, the dynamic layered-recurrent neural network was developed by Turabieh et al. [2] to recover missing data. Data mashup-based web technology was proposed by Elmisery et al. [3] to serve a centralized environmental monitoring service.

In addition, the programming languages are compiler-based, which means that all layers and their activation/deactivation are determined in a development stage. The contexts cannot be completely predicted at the development stage [4], healthcare applications, which limit the applications of language. Therefore, in this paper, we introduce an encapsulation mechanism-based context-orient programming paradigm (COP) in IoMT to reduce the occurrences of above-mentioned crosscuts. In COP, the application’s codes are divided into different parts (i.e., layers), which is a new block-structured construction. Each layer is related to other contexts, where the layer activation and deactivation mechanism is provided to ensure that the codes in different layers can be executed. As a result, the application can adjust its behaviors according to context. Some extensions of Java for COP, such as JCOP [5] and EventCJ [6], have been implemented.

Virtual machine (VM), which has been considered as an intermediate layer between the executing application and the hardware [7], is widely used in big data process and analysis [8, 9], as well as increasing the possibility for dynamic code evolution. Object proxy [10] is advocated as a flexible mechanism to dynamically adapt behavior of objects to adapt the behavior of a single object. Therefore, this paper proposes a new approach, which incorporates object proxy into VM, to enhance the flexibility of applications in terms of context-based dynamical behavior adjustment. Unlike above-mentioned COP languages, based on VM, layer activation and deactivation in our approach are used to monitor the changes of context and dynamically activate or deactivate layers so that the application can adapt its behavior in context.

In the perspective of VM, a layer is a Java class. In order to support layer activation and deactivation mechanism on VM level, the object proxy is used in our approach. An object at runtime is actually an object list, which is composed of an object of a base class and objects of layer classes. The base class object is considered as a proxy object, where each method invocation is redirected to other objects in the object list. As a result, codes in the layer are executed to achieve the layer activation. Similarly, the layer deactivation is also achieved by removing or deactivating other objects in the list.

Furthermore, dynamic layer replacement can be achieved in our approach via object evolution. As an object is represented as a list, when VM monitors the changes of context, VM can evolve an object at runtime by inserting a new object of a layer class into it or deleting an object from it. Once the layer is replaced, VM removes the objects of layered classes in the removed layer from object lists and inserts new objects of layered class in the new loaded layered classes in the new layer into object lists. As a result, the application can adjust its behavior to fit the changes of contexts through dynamic layer replacement.

On the other hand, the heap and stack need to be scanned by the VM to find out all objects that to be evolved, which leads to a lot of overhead for the object evolution at runtime. To relieve the overhead, the objects are evolved lazily in our approach. Furthermore, object evolution can lead to type violation [11]. Therefore, this paper incorporates heap and address into RFT-FJ [12] to model the objects and evolutions, where the semantics of field access and method invocation on objects are described in detail. Next, the impact of the evolution on type safety is analyzed. Afterwards, the constraints on object evolution are proposed to avoid the type violation. Finally, the object evolution is presented by extending Java VM to verify our application.

The remainder of this paper is structured as follows. In Section 2, we illustrate our approach by an application. In Section 3, the related work is given. In Section 4, our approach is described. In Section 5, we present the implementation and evaluation of our approach. Conclusion is finally presented in Section 6.

2.1. The Internet of Medical Things

Rodrigues et al. [13] reviewed technological advances made so far which can be used in IoMT and then analyzed the challenges to be overcome. Ullah et al. [14] presented a new semantic model for patients’ e-health based on existing technologies, which are used to deploy IoT in the field of medical and smart health care. Turabieh et al. [2] introduced a dynamic L-RNN from artificial intelligence to recover missing data from IoMT applications to guarantee high quality of services to the end users. Kernec et al. [15] presented place of radar for assisted living in the context of IoT for health and pointed out how important the context is. Elmisery et al. [3] used data mashup from web technology to serve a centralized environmental monitoring service. Haoyu et al. [16] used cloud computing to provide real-time sleep apnea detection. They both introduced technologies from other research areas to IoMT. Similarly, we introduce COP programming paradigm from programming language area to reduce codes’ scatter and tangle in IoMT applications. Joyia et al. [1] pointed out some challenges in IoMT, where software implementation is still full of challenges. We believe our work makes an important step toward resolving these challenges.

2.2. Object Evolution

In order to support context awareness, object composition has been used to represent objects with some dynamic behaviors [7, 17].

An object evolution approach is proposed in [7]. The approach is based on composition and delegation while our approach is based on composition and proxy. This is the most important difference between them. Compared with delegation, proxy is easier to achieve semantic analysis and implementation of layer activation and deactivation, although it suffers from a little less flexibility.

In [18], an evolution approach based on version consistency is proposed, which is similar to our evolution approach. However, its version consistency is applied for the evolution of components in distributed system while ours is applied for objects. This is the most important difference between the two approaches in terms of version consistency.

In [17], object composition and delegation with a static type discipline are also used for dynamic behavior adaptation of objects. However, the object in [17] is only explicitly composed while the composition is implicit in our approach. Furthermore, object composition in [17] is used for dynamic inheritance and code reuse while object composition in our approach is used for dynamic behavior adaptation of the program.

Granule-oriented programming [19] uses fitness to determine which components are available for applications. In [12], predicate is applied to determine the applicability of context-specific methods. Our approach also uses predicate for the similar purpose. However, there are some differences between them. Predicate in [19] is not formally defined while fitness in [12] and our approach is formally defined as a predicate method. Moreover, fitness in [12] is applied to select context-specific methods of composed classes while predicate in our approach is applied to select context-specific methods of composed objects.

In [20], various problems of software evolution and their corresponding solutions are presented and classified into several types. Some required operations on evolution are formally described and analyzed to ensure the consistency before and after evolution.

2.3. Context-Oriented Programming

In [6], an approach that incorporates features of AOP is presented to implement features of COP. Both it and our approach share some common features. Firstly, the predicate is used to determine the applicability of the context-specific method. Secondly, layer activation is on a per-instance basis rather than a per-thread basis. However, our approach is VM-based, while the approach presented in [6] is compiler-based. Although the approach incorporates features of AOP, dynamic aspect weaving is not incorporated. Therefore, the approach does not support dynamic layer addition while our approach supports it. This is a significant difference between the two approaches.

ContextFJ [21] is an extension of Featherweight Java, which models language mechanisms for context-oriented programming. Although ContextFJ and our approach both directly express context-dependent behavior, there are still some differences between them. Firstly, ContextFJ and our approach use block-structured constructs and object proxy for dynamic behavior adaptation, respectively. Secondly, ContextFJ does not allow layers to introduce new methods, but our approach does.

3. System Model

In this section, we first describe problems caused by Java-based COP languages by a simple healthcare application and then propose object evolution approach, a VM-centric approach, to solve them.

A healthcare application code snippet written in a Java-based COP language is shown in Figure 1, which is used to display healthcare schedule information for users. If the current device is a doctor’s computer, the application can show more details about medical histories of their patients and must not show patients’ sensitive personal information, protecting their personal privacy. On the other hand, if running on patients’ smart watches, the application can briefly show important medical schedule, including some personal information.

The basic part of the application is a Java program, and classes in the part are called basic ones, not considering runtime context. The rest are two layers L1 and L2. A layer is defined by the keyword layer, consisting of a predicator, and a Java class, called layered class. The predictor is used to check whether or not the layer matches current execution context. If so, the methods in the layered class can be executed.

In compiler-based COP languages, layer activation and deactivation are part of codes, which means if some layers no longer match the current context, an application has to rewrite, recompile, and re-execute. This not only shortens its life cycle but also makes it not adjust its behaviors to the context well.

For solving such problems, our approach proposes that VM is responsible for layer activation and deactivation. That is, each time methods in basic classes are invoked, VM is responsible for selecting and executing methods in proper layers, which match the current execution context. As a result, each time a layer has bugs or no longer matches new execution context, a new layer can easily be dynamically loaded by VM to replace the old layer.

To achieve our approach, the object structure is extended, as shown in Figure 2. An object at runtime is represented into a double linked list. The first element of the liked list is an object of a based class. The other elements are objects of layer classes. For example, when the layer L1 is activated, a runtime object O is composed of Ob and , an object of the base class calendar and that of the layered class, respectively. VM redirects all method invocations on Ob to these as long as L1 matches the current execution environment. Actually, Ob is considered as an object proxy.

On the other hand, if L1 is replaced with L1′, VM evolves O to O′ by replacing with , a new object created by VM. Since only Ob points to , the redirection can avoid scan heap and stack.

Furthermore, if there are many objects containing objects of L1, they must be not immediately evolved because they may be accessed very soon. Therefore, our approach evolves these objects in a lazy manner, that is, an object is evolved only when it is accessed. To check whether or not an object is evolved, a version number is added to structures of a class and an object. The version numbers of a classes and an object are initialized when they are loaded and created, respectively. Specifically, when a layer is replaced, due to context mismatch, the version number of a base class is increased by 1 only if the same name layered class in the layer is loaded. And the version number of the layered class is initialized with that of the base class. When an object is created, its version number is initialized with that of its class. If version numbers of a class and an object are different, then the object will be evolved when it is accessed, and version numbers of all elements in the object are updated. As a result, our approach may avoid scan heap and stack to evolve objects and improve object evolution efficiency.

Our object evolution approach is summarized as follows:(1)For an object O represented as , if there is a method invocation on it, the version numbers of Ob are firstly compared with those of its base class C.(2)If equal, the object O is not evolved and the invocation will be executed. Specifically, if the field “real_obj” in Ob points to null, which means is null, the method will be resolved in C and executed. Otherwise, the method will resolve the object CL pointed by the real_obj field in Ob. As a result, methods which defined layered classes are executed(3)If not equal, which means at least a layer replacement has occurred, then the object O has to be evolved by VM. Specifically,(i)If is null, then an object of a layered class named C is firstly created, and composed a double linked list with Ob. Furthermore, the version number of Ob will be updated. Finally, VM executes step 1 again.(ii)If is not null, then will be replaced with a new object of a new layered class C from a new layer. This is achieved by redirecting the real_obj field in Ob to the newly created object and the field proxy_obj in to Ob. Figure 2(b) shows the evolution process. Furthermore, the version number of Ob will be updated. Finally, VM executes step 1 again.

At runtime, objects may be replaced, according to Step 3, which results in type violation. In the next section, we model objects and their evolutions and then formally describe field access and method invocation on objects. Afterwards, some constraints are proposed to ensure that object evolution does not cause type violation.

4. Object Evolution

We first formally describe classes, objects and field access, and method invocation on objects. Afterwards, we analyze the impact of objects’ evolutions on them and make some constraints to ensure such evolutions do not result in type violation. In this paper, classes are defined as sets and objects are formally described as a set of addresses in a heap.

Definition 1 (class definition). A class C can be represented by a set composed of fields and methods, where is the abbreviation of , and T and f denote a type and a field name, respectively. is similar.
Two auxiliary functions Sf and Sm return the field set and the method set of a specific class C, whose definitions are given as follows:

Definition 2 (combination class). is a combination of two same name classes, where C and CL denote a base class C and a layered class C, respectively. The combination contains all elements of C and CL. is an object of , which can be described as the two-tuple and .

Definition 3 (object definition). An object is represented as a two-tuple or . The first element is the type of the object, and the second one is its fields and addresses of these fields, where l denotes an address.
Based on the above definitions, we formally describe field access and method invocation on objects by a computation state. A computation state can be described as the pair of an expression and heap, (e, ), where an expression may be a field access l.f or a method invocation . Therefore, the reduction relationship can be described by e, , , which indicates that a computation state e, can be reduced to another state e′, . Furthermore, denotes the reflexive transitive closure of .
The rule for field access (E-PROJ1 and E-PROJ2): for an object, if its address in the heap is l, its type is C or , and the field f has been defined, then the field access can be reduced to its value.
The rule for the method invocation (E-LINVK, E-LINVK2, E-LINVK3, and E-CINVK): compared with field access, the method invocations are more complex, since they contain context match and object evolution. Their main ideas are (1) if the receiver of a method invocation is only an object of the base class C, the invocation is directly reduced to its method body, where parameters are replaced by arguments, and this is replaced by the receiver and (2) if the receiver of a method invocation is an object of a combination class , the method invocation will be redirected to the same type method in a layered class CL. If the layer which contains CL matches the current context, then the invocation can be reduced to the method body of the method. Otherwise, the object has to be evolved. Specifically, rules for method invocation are described as follows:(i)E-INVK rule: for an object O represented as , its address in the heap is l, and its type is a base class C. If the method m is resolved in C, then the invocation is directly reduced to its method body, where parameters are replaced by arguments , and this is replaced by l.(ii)E-LINVK rule: for an object O represented as , its address in the heap is l, and its type is a combination class . If a method m is resolved in CL and the layer containing CL matches the current context, then the invocation can be reduced to the method body in CL, where parameters are replaced by arguments , and this is replaced by l.(iii)E-LINVK2 rule: for an object O represented as , its address in the heap is l, and its type is a combination class . If a method m is resolved in CL but the layer does not match the current context, and a proper layer, which matches the current context, cannot be found out or provided, then the invocation can be reduced to the method body of the same type method in the base class C, where parameters are replaced by arguments , and this is replaced by l.(iv)E-LINVK3 rule: for an object O represented as , its address in the heap is l, and its type is a combination class . If a method m is resolved in CL but the layer does not match the current and a proper layer can be found out or provided, then the object is firstly evolved by VM, that is, an new object of is created and replaces the object of CL in O, and then the object’s type is also updated to . Afterwards, the invocation is reduced to the method body of the same type method in , where parameters are replaced by arguments , and this is replaced by l.(v)E-CINVK rule: for an object O represented as , its address in the heap is l, and its type is a combination class . If a method m is invoked by another method in the same layer class, then the context match is not checked and the invocation is reduced to its body, where parameters are replaced by arguments , and this is replaced by l.In the above-mentioned rules, the function mbdoy () models the semantic of the method resolution in Java. It returns a method body of a method in a class. More details about it are shown in [7, 12]. “predicate() true IN CL” represents the layer L that matches the current context while “predicate() false IN CL” represents the layer L that does not match.
The notation in the E-LINVK3 rule denotes object evolution. Object evolution may result in the type violation when evolved object is being accessed. For example, if E-LINVK1 is interrupted after it executes for a moment, then E-LINVK3 is executed and an object l is evolved. When E-LINVK1 is executed again, the method may not exist, due to l’s change, yielding the type violation. Therefore, some constraints should be proposed for object evolution so that the type violation can be avoided.
Next, we firstly formally describe object evolution and present some constraints on it, which are shown in the following definition.

Definition 4 (valid object evolution). Assume that an object l is evolved to , denoted by ; since a layered class CL is replaced by another well-formed , we have , , , . Furthermore, the evolution is valid only if the following conditions hold:(1) m is in stack, if , then (2) , f is only accessed by (3), and then m type(m, CL2) <: mtype(m, CL1)The first constraint requires that object evolution cannot have influence on running methods. This ensures these methods still exist after object evolution, avoiding runtime errors. The second constraint ensures fields in a layered class are only accessed by methods in the class, which ensures accessing fields do not lose after object evolution. The function mtype [7, 12] returns the type of a method in a class. The third constraint requires to have the same methods as , which ensures there are no dynamic-type violations after objects’ evolution.
Based on the above definition, if base classes and layer classes are well typed, the following theorem can ensure type violation does not occur after object evolution. We denote expressions before and after objection evolution by e and , respectively.

Theorem 1. Assume that e contains l and that results in ; if e has the property of type-safe and all layer class CL in each replacement are well typed, then has the property of type-safe too.

The theorem intuitively indicates that if any component of a well-typed expression e is replaced with another well-typed component, then e is still well typed. This is very similar to industrial products in the real world. For example, if a component of a qualified car is replaced with another qualified one, then the car is still qualified.

Proof. We prove the theorem by induction.(1)Basic: if l is unchanged, then e is unchanged. According to the assumption, the theorem holds.(2)Reduction: assume that results from , which is caused by replacing . If e is type-safe, is type-safe.

Proof by Contradiction. If has type violation caused by . Without loss of generality, assume that , :(i)If contains a static-type violation, according to the static-type violation definition [11], we have and or and .(a)Firstly, if there exists and the method m is being executed, then according to the first constraint of valid object evolution, m is not in the stack, e.g. is not being executed, which is contradicted with the assumption.(b)Secondly, if there exists and m is not being invoked, then according to the condition that e and CL are well typed, only base method invocations can be redirected to the corresponding methods of layered classes. Therefore, we have , which contradicts with the assumption.(c)If and , then . According to the second constraint of valid object evolution, fields in a layered class only are accessed only by methods in the same class. Because m is not in the stack, the field f is not accessed. The result is contradicted with the assumption. Finally, the theorem holds.(ii)If contains a dynamic-type violation, then we have . Assume that l’s type is and ’s type is . According to the third constraint of valid object evolution and the subclass relationship record, we have , which is contradicted with the assumption. So, the dynamic-type violation is nonexistent. The theorem holds.

5. Implementation and Evaluation

In this section, we briefly describe how to extend a Java virtual machine to implement runtime object evolution, a VM-centric approach.

5.1. Implementation

JamVM is a compact Java virtual machine (JVM) which conforms to JVM specification version 2. In comparison to most other VMs, JamVM is extremely small; hence, it is easier for us to extend. In order to implement object evolution, we mainly extend JamVM’s class loader, interpreter, resolution, and memory allocation.

JamVM represents objects with the structure object. In order to support object evolution based on object proxy, we added two pointers real_obj and proxt_obj into the structure. The extended structure is shown in Figure 2(a). Each time an object is created, these pointers are initialized to null. At runtime, they are used to create a double-linked object list, a runtime object. Furthermore, a variable of integer type, flag, is added into the structure. If its value is zero, VM does not check whether or not a layer matches the current context. Otherwise, the check is executed.

In our approach, objects are lazily evolved. As mentioned above in Section 3, lazy evolution is implemented by comparisons of version numbers of a class and an object. Therefore, we also added a variable of integer type, version, into the object and classblock which is a structure to represent as loaded classes. Afterwards, we extend the class loader so that version may correctly initialize each time a class is loaded. In general, each time a base class is loaded, its version’s value is initialized with 0. Each time a layered class is loaded or removed due to a layer replacement, its version’s value is increased by 1. On the other hand, each time a layered class is loaded, its version’s value is initialized with that of a base class with the same name. We also extend the new instruction so that when an object is created, its version’s value is initialized with the version’s value of its class.

The interpreter is responsible for dealing with method invocation. The normal execution process of method invocation is illustrated in the left of Figure 3. Each time dealing with an instruction for method invocation, the resolution module firstly resolves the invoked method and then the execution module executes the resolved method. However, if the receiver is an object list, the process should be changed, as shown in Figure 3. Particularly, a compare module and evolution module is added into method invocation process.

We extend semantics, three instructions in the interpreter module of JamVM to achieve the change. The three instructions are invokevirtual, invokespecial, and invokestatic, respectively, which are responsible for doing with method invocations in different conditions.(i)If proxy_obj and real_obj of the receiver of the invocation are null, the receiver is only an object of a base class. Firstly, version numbers of the object and its class are compared. If equal, the method resolution just looks for the invoked method in the based class and executes its body. This is consistent with the semantic of E-INVK. Otherwise, the object is evolved. If not equal, VM evolves the object. If evolution succeeds, context match is checked. If it matches, then the resolution module looks for its method body in real_obj and executes it. Otherwise, the module looks for its method body in the object and executes it.(ii)For the receiver, if its proxy_obj is null but its real_obj is not null, which means that the receiver is an object list containing at least two objects, the method invocation occurs on the first object of the list, an object of a base class. In this case, version numbers of the first object in the list and its class need to be compared. If they are not equal, the receiver is evolved by VM. If the evolution succeeds and context match is checked, then the resolution module looks for its method body in real_obj and executes it. Otherwise, the module looks for its method body in the object and executes it.(iii)For the receiver, if its a proxy_obj, the method invocation occurs on an object of layered class. In this case, version numbers of the first object in the list and its class need to be compared. If they are not equal, the receiver is evolved by VM. If the evolution succeeds, then the resolution module looks for its method body in real_obj and executes it. Otherwise, the module looks for its method body in the object and executes it.

For object evolution by triggering layer replacement, the interpreter searches a specific directory to look for a proper layer which holds the following conditions:(i)Matches the current context(ii)Contains a layer class, which has the same type method with the current invoked method

Once VM finds out a proper layer, layered classes in it are loaded and new objects are created to evolve the receiver of the current method invocation.

In this section, our implementation proves that our approach is feasible. In the future work, we plan to support object evolution in a multithread context.

5.2. Evaluation

In this section, we discuss our runtime measurements. For illustration purposes, methods in classes and layers are called as plain methods and layered methods, respectively. We set up micromeasurements to assess the performance of the execution of the layered method. Our measurements were all run on 2.2 GHz Intel Core2Duo with 3 GB of RAM, running Ubuntu 10.04 LTS.

Java Grande benchmark framework [14] contains all kinds of method invocations and object creations and access in Java to evaluate performance of a Java VM, for example, class/instance method invocations and class/instance object creations. To evaluate our approach, we add at least two layers for each kind of method invocations and object creations and access in Java Grande benchmark framework, respectively. One of the two layers fits the current execution environment while the others do not fit. On the other hand, both JamVM and our extension to JamVM run on Ubuntu 10.04 LTS operation system with Java 1.6 version.

Based on our experiment environment, we first evaluate the performance of the execution of the layered method and then compare the execution performance of method invocations on an extension to JamVM and on standard JamVM. The benchmark includes synchronized and nonsynchronized plain instance methods that calculate the power of a given number. The main method in the benchmark contains four types of plain method calls: synchronized and nonsynchronized instance methods, and calls to synchronized and nonsynchronized class methods. Each type of method call is executed times.

5.2.1. Performance of Layer Replacement Based on Object Evolution

After 17 times execution of benchmark, the results are shown in Figure 4. The results show that the layer replacement efficiency caused by class method invocation is 468/ms. The layer replacement efficiency caused by instance method invocation is 414/ms. The difference between the two efficiencies are caused by the following reasons. Firstly, class method invocation has nothing to do with object evolution; hence, new object creations and object list constitutions are unnecessary. Moreover, compared to the synchronized method, the influence of an asynchronized method on the layer replacement is smaller. The reason is because execution of unlocking the asynchronized method needs more time.

5.2.2. Performance of Method Call Based on Object Evolution

The layer replacement based on object evolution is implemented by the extension of a virtual machine, which could impact the execution performance of method invocations on objects. In order to evaluate the influence, we compare the execution performance of method invocations on the standard JamVM and its extension by running benchmark 17 times on them, respectively.

The experiment results are shown in Figure 5. The results show that the execution performance of method invocation on the extended virtual machine is from 6% to 10% lower than that on the standard JamVM. Particularly, the execution performance of instance method invocations on the extension is close to 90% of that on standard JamVM. The execution performance of synchronization class method invocations on the extension is close to 94% of that on standard JamVM. The main reason for the low performance is that the extension JamVM has to check whether or not the receiver of a method invocation contains objects of layered classes. Furthermore, it needs to check whether or not the invoked method matches the current context.

5.3. Discussion

Our approach supports layer replacement by extending object represented in Java VM and semantics of method resolution, which gives rise to overhead. In space complexity, an object in our approach may cost extra tens of bytes because it contains an object list. In time complexity, as mentioned above in Implementation section, our approach usually does two extra operations. The first one is to locate an object in an object list, and the second one is to execute the fitness method. They are the root cause to overhead, which ranges from 6% to 10% in our experiment. In the future, we intend to introduce a cache mechanism to reduce an object in size and avoid fitness method execution as soon as possible.

6. Conclusion

Healthcare applications have to run on various medical devices, which have their own particular contexts. These contexts crosscut healthcare applications’ codes, making them more scattered and tangled and increasing costs of their development and maintenance. Some COP languages address crosscut concern; however, they have some deficits that new layers cannot be loaded at runtime to replace layers which no longer match the current context.

In this paper, we propose a new approach to support context-based dynamic behavior adjustment of applications. Unlike existing COP languages, our approach uses object proxy in the VM level to support layer activation and deactivation. Furthermore, as our approach is based on VM, it more easily leverages VM to dynamically replace layers so that applications can better adapt new context. In order to verify our approach, we first formally describe it and prove it, ensuring type-safety properties of applications only if some constraints are held. Finally, we present how to implement our approach by extending Java VM.

Data Availability

The experiment platform (i.e., extended JamVM) and results used to support the findings of this study have been deposited in https://github.com/zcp/jvm_extension.git, and they are available from the corresponding author upon request.

Conflicts of Interest

The authors declare that there are no conflicts of interest regarding the publication of this paper.

Acknowledgments

This research was supported in part by a grant from NSFC under Grant nos. 61571286 and 61640219.