Lors du développement d'une application client-serveur, j'ai toujours une question, mais comment vais-je la déployer sur le serveur, l'emballer dans jar / war / docker après avoir écrit le code, puis encore besoin de le transférer sur le serveur, et toujours avoir beaucoup de gestes pour simplement pousser un morceau de code sur le serveur.
Ce serait bien de simplement passer le code au serveur en tant que lambda, tout comme nous passons un lambda à une fonction, nous le transmettons également au serveur.
Mais j'avais une idée de comment rendre ce processus plus facile, et j'ai fait quelque chose.
1 | var query = TcpQuery
2 | .create(IEnv.class).host("myserver.com").port(9988)
3 | .build();
4 |
5 | query.apply(
6 | env -> env.processes().stream().filter(
7 | p -> p.getName().contains("java")
8 | )
9 | .collect(Collectors.toList())
10| ).forEach(System.out::println);
Voici le code java,
Lignes 1 à 5 incluses et 10 - travail sur le client
6 9 ( env->...)
, Java (11).
6 9 ( ) , , , - deploy, IDE (Idea/Eclipse/etc...).
, Serializable Lambda Java, - , , .. deploy api ( ).
IEnv:
public interface IEnv {
List<OsProc> processes();
}
public class OsProc implements Serializable {
public Optional<Integer> getPpid(){ return ... }
public int getPid(){ return ... }
public void setPid(int pid){ ... }
public String getName(){ return ... }
public Optional<String> getCmdline(){ return ... }
}
var query = TcpQuery
.create(IEnv.class).host("myserver.com").port(9988)
.build();
query.apply(
env -> env.processes().stream().filter(
p -> p.getName().contains("java")
)
.collect(Collectors.toList())
).forEach(System.out::println);
- ?
Java
, Client.java
- - Client.class
query.apply() - env -> env.proc...toList())
query.apply():
( Client) ( lambda1)
- (Client.class)
-
-
-
//
query.apply()
, -, IDE .
?
, pet project-:
v 1.0 https://github.com/gochaorg/trambda/releases/tag/1.0
maven
<dependency>
<groupId>xyz.cofe</groupId>
<artifactId>trambda</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>xyz.cofe</groupId>
<artifactId>trambda-core</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>xyz.cofe</groupId>
<artifactId>trambda-tcp</artifactId>
<version>1.0</version>
</dependency>
, (TCP)
OsProc.java - ( )
IEnv.java - ( )
LinuxEnv.java - Linux - IEnv
:
package xyz.cofe.trambda.demo.api;
import org.junit.jupiter.api.Test;
public class LinuxEnvTest {
@Test
public void test(){
var env = new LinuxEnv();
env.processes().stream()
.filter(p->p.getName().equalsIgnoreCase("java"))
.forEach(System.out::println);
}
}
LinuxEnv - , :
package xyz.cofe.trambda.demo.api;
import java.util.ArrayList;
import java.util.List;
import xyz.cofe.io.fs.File;
public class LinuxEnv implements IEnv {
@Override
public List<OsProc> processes(){
ArrayList<OsProc> procs = new ArrayList<>();
File procDir = new File("/proc");
procDir.dirList().stream()
.filter( d -> d.getName().matches("\\d+") && d.isDir() )
.map(OsProc::linuxProc)
.forEach(procs::add);
return procs;
}
}
, /proc , ( Linux / /proc)
(git commit 67ec260)
> git clone https://github.com/gochaorg/trambda.git
«trambda»...
remote: Enumerating objects: 978, done.
remote: Counting objects: 100% (978/978), done.
remote: Compressing objects: 100% (464/464), done.
remote: Total 978 (delta 308), reused 862 (delta 195), pack-reused 0
: 100% (978/978), 715.70 KiB | 559.00 KiB/s, .
: 100% (308/308), .
user@user-Modern-14-A10RB:22:10:35:~//sample-tr:
> cd trambda/trambda-demo/tr-demo-api/
user@user-Modern-14-A10RB:22:10:49:~//sample-tr/trambda/trambda-demo/tr-demo-api:
> mvn clean package install
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 13.933 s
[INFO] Finished at: 2021-04-18T22:11:11+05:00
[INFO] ------------------------------------------------------------------------
target jar
user@user-Modern-14-A10RB:22:13:13:~//sample-tr/trambda/trambda-demo/tr-demo-api:
> ll target/
48
drwxrwxr-x 10 user user 4096 18 22:11 ./
drwxrwxr-x 4 user user 4096 18 22:11 ../
drwxrwxr-x 3 user user 4096 18 22:11 classes/
drwxrwxr-x 3 user user 4096 18 22:11 generated-sources/
drwxrwxr-x 3 user user 4096 18 22:11 generated-test-sources/
drwxrwxr-x 2 user user 4096 18 22:11 maven-archiver/
drwxrwxr-x 3 user user 4096 18 22:11 maven-status/
drwxrwxr-x 4 user user 4096 18 22:11 site/
drwxrwxr-x 2 user user 4096 18 22:11 surefire-reports/
drwxrwxr-x 3 user user 4096 18 22:11 test-classes/
-rw-rw-r-- 1 user user 6337 18 22:11 tr-demo-api-1.0-SNAPSHOT.jar
github
user@user-Modern-14-A10RB:22:37:25:~//sample-tr: > wget https://github.com/gochaorg/trambda/releases/download/1.0/trambda-tcp-serv-cli.zip --2021-04-18 22:37:31-- https://github.com/gochaorg/trambda/releases/download/1.0/trambda-tcp-serv-cli.zip github.com (github.com)... 140.82.121.4 github.com (github.com)|140.82.121.4|:443... . HTTP- . ... 302 Found : https://github-releases.githubusercontent.com/350075998/47380d00-9b40-11eb-90a4-4e353f42e67c?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210418%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210418T173731Z&X-Amz-Expires=300&X-Amz-Signature=97ade1f58bfbe1eaa320805179987e8c4df730b9f5eddf24c05662fb676caafe&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=350075998&response-content-disposition=attachment%3B%20filename%3Dtrambda-tcp-serv-cli.zip&response-content-type=application%2Foctet-stream [] --2021-04-18 22:37:31-- https://github-releases.githubusercontent.com/350075998/47380d00-9b40-11eb-90a4-4e353f42e67c?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20210418%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210418T173731Z&X-Amz-Expires=300&X-Amz-Signature=97ade1f58bfbe1eaa320805179987e8c4df730b9f5eddf24c05662fb676caafe&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=350075998&response-content-disposition=attachment%3B%20filename%3Dtrambda-tcp-serv-cli.zip&response-content-type=application%2Foctet-stream github-releases.githubusercontent.com (github-releases.githubusercontent.com)... 185.199.111.154, 185.199.108.154, 185.199.109.154, ... github-releases.githubusercontent.com (github-releases.githubusercontent.com)|185.199.111.154|:443... . HTTP- . ... 200 OK : 12107487 (12M) [application/octet-stream] : «trambda-tcp-serv-cli.zip» trambda-tcp-serv-cli.zip 100%[========================================================================================================================================>] 11,55M 3,75MB/s 3,1s 2021-04-18 22:37:35 (3,75 MB/s) - «trambda-tcp-serv-cli.zip» [12107487/12107487] user@user-Modern-14-A10RB:22:37:35:~//sample-tr: > ll 11836 drwxrwxr-x 3 user user 4096 18 22:37 ./ drwxr-xr-x 11 user user 4096 18 22:00 ../ drwxrwxr-x 10 user user 4096 18 22:10 trambda/ -rw-rw-r-- 1 user user 12107487 12 03:36 trambda-tcp-serv-cli.zip user@user-Modern-14-A10RB:22:37:42:~//sample-tr: > unzip trambda-tcp-serv-cli.zip Archive: trambda-tcp-serv-cli.zip creating: trambda-tcp-serv-cli/ creating: trambda-tcp-serv-cli/jars/ inflating: trambda-tcp-serv-cli/jars/asm-9.1.jar inflating: trambda-tcp-serv-cli/jars/jline-2.14.6.jar inflating: trambda-tcp-serv-cli/jars/iofun-1.0.jar inflating: trambda-tcp-serv-cli/jars/groovy-swing-3.0.7.jar inflating: trambda-tcp-serv-cli/jars/groovy-console-3.0.7.jar inflating: trambda-tcp-serv-cli/jars/groovy-xml-3.0.7.jar inflating: trambda-tcp-serv-cli/jars/trambda-tcp-serv-cli-1.0.jar inflating: trambda-tcp-serv-cli/jars/ecolls-1.10.jar inflating: trambda-tcp-serv-cli/jars/trambda-core-1.0.jar inflating: trambda-tcp-serv-cli/jars/slf4j-api-1.7.25.jar inflating: trambda-tcp-serv-cli/jars/asm-tree-9.1.jar inflating: trambda-tcp-serv-cli/jars/asm-util-9.1.jar inflating: trambda-tcp-serv-cli/jars/fs-1.2.jar inflating: trambda-tcp-serv-cli/jars/logback-classic-1.2.3.jar inflating: trambda-tcp-serv-cli/jars/trambda-tcp-1.0.jar inflating: trambda-tcp-serv-cli/jars/groovy-groovysh-3.0.7.jar inflating: trambda-tcp-serv-cli/jars/groovy-templates-3.0.7.jar inflating: trambda-tcp-serv-cli/jars/asm-analysis-9.1.jar inflating: trambda-tcp-serv-cli/jars/text-1.0.jar inflating: trambda-tcp-serv-cli/jars/logback-core-1.2.3.jar inflating: trambda-tcp-serv-cli/jars/groovy-3.0.7.jar inflating: trambda-tcp-serv-cli/jars/cbuffer-1.3.jar creating: trambda-tcp-serv-cli/bin/ inflating: trambda-tcp-serv-cli/bin/trambda-tcp-serv.bat inflating: trambda-tcp-serv-cli/bin/trambda-tcp-serv user@user-Modern-14-A10RB:22:37:50:~//sample-tr: > rm trambda-tcp-serv-cli.zip
trambda-tcp-serv-cli/jars
ser@user-Modern-14-A10RB:22:40:47:~//sample-tr:
> cp -v trambda/trambda-demo/tr-demo-api/target/tr-demo-api-1.0-SNAPSHOT.jar trambda-tcp-serv-cli/jars/
'trambda/trambda-demo/tr-demo-api/target/tr-demo-api-1.0-SNAPSHOT.jar' -> 'trambda-tcp-serv-cli/jars/tr-demo-api-1.0-SNAPSHOT.jar'
:
> cat trambda/trambda-tcp-serv-cli/src/test/samples/sample-1.groov
// xyz.cofe.trambda.demo.api.LinuxEnv
// 9988, IP
app.service( "0.0.0.0:9988", new xyz.cofe.trambda.demo.api.LinuxEnv() ) {
daemon false
//
security {
// API/
allow {
// method("System") {
// methodOwner ==~ /java.lang.System/ && methodName in ['gc']
// }
// field( "System.out" ) {
// fieldOwner ==~ /java.lang.System/ && fieldName in ['out','in','err'] && readAccess
// }
invoke( 'Java compiler' ){
methodOwner ==~ /java\.lang\.invoke\.(LambdaMetafactory|StringConcatFactory)/
}
invoke( 'Java collections' ){
methodOwner ==~ /java\.util\.(stream\.(Stream|Collectors)|(List))/
}
invoke( 'Java lang' ){
methodOwner ==~ /java\.lang\.String/
}
invoke( 'Api '){
methodOwner ==~ /xyz\.cofe\.trambda\.demo\.api\.(IEnv|OsProc)/
}
}
// -
deny {
any("ban all")
}
}
}
user@user-Modern-14-A10RB:22:56:08:~//sample-tr:
> bash ./trambda-tcp-serv-cli/bin/trambda-tcp-serv -s trambda/trambda-tcp-serv-cli/src/test/samples/sample-1.groovy
# [main] INFO x.c.t.tcp.serv.cli.TcpServerCLI - starting xyz.cofe.trambda.tcp.serv.cli.TcpServerCLI
# [main] INFO x.c.t.tcp.serv.cli.TcpServerCLI - executeScript( "trambda/trambda-tcp-serv-cli/src/test/samples/sample-1.groovy", UTF-8 )
# [main] INFO x.c.t.tcp.serv.cli.TcpServerCLI - registry class xyz.cofe.trambda.demo.api.LinuxEnv on 0.0.0.0:9988
# [main] INFO x.c.t.tcp.serv.cli.TcpServerCLI - starting service xyz.cofe.trambda.demo.api.LinuxEnv@55e7a35c on /0.0.0.0:9988
# [main] DEBUG x.c.t.tcp.serv.cli.TcpServerCLI - create server socket
# [main] DEBUG x.c.t.tcp.serv.cli.TcpServerCLI - bind server socket /0.0.0.0:9988
# [main] DEBUG x.c.t.tcp.serv.cli.TcpServerCLI - server started
, ,
package xyz.cofe.trambda.demo.client;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import xyz.cofe.trambda.demo.api.IEnv;
import xyz.cofe.trambda.tcp.TcpQuery;
public class ClientTest {
@Test
public void test01(){
var query = TcpQuery
.create(IEnv.class).host("localhost").port(9988)
.build();
query.apply(
env -> env.processes().stream().filter(p ->
p.getName().contains("java"))
.collect(Collectors.toList())
).forEach(System.out::println);
}
}
, , - ..
?
- ..
, :
// TCP
ServerSocket ssocket = new ServerSocket(port);
//
ssocket.setSoTimeout(1000*5);
//
server = new TcpServer<IEnv>(
//
ssocket,
//
s -> new LinuxEnv(),
//
SecurityFilters.create(s -> {
// -
s.allow( a -> {
// API
a.invoke("demo api", c->
c.getOwner().matches(
"xyz\\.cofe\\.trambda\\.tcp\\.demo\\.([\\w\\d]+)"));
//
a.invoke("java collections api", c->c.getOwner().matches(
"java\\.util\\.(List)|java\\.util\\.stream\\.([\\w\\d]+)"));
// Java
a.invoke("java lang api", c->
c.getOwner().matches("java\\.lang\\.(String)"));
// Java
a.invoke("java compiler", c->
c.getOwner().matches(
"java\\.lang\\.invoke\\.(LambdaMetafactory|StringConcatFactory)"));
});
//
s.deny().any("by default");
})
);
// Thread
server.setDaemon(true);
//
server.start();// TCP
ServerSocket ssocket = new ServerSocket(port);
//
ssocket.setSoTimeout(1000*5);
,
,
,
Java
LambdaMetafactory
StringConcatFactory +
/ - . SecurityFilters.java / PredicateBuilder#field
, Object.toString() ,
?
, , RMI, gRPC ?
, . /:
/
/ /
/
//…
-
..
… ..
,
|
Java-RMI |
SOAP |
REST-JSON |
SQL |
GraphQL |
Hadoop |
|
+ |
+ |
+ |
+ |
+ |
+ |
|
+/- |
+/- |
- |
- |
+ |
- |
|
+/- |
+/- |
+ |
+ |
- |
+ |
|
- |
- |
- |
+ |
- |
+ |
|
- |
- |
- |
+ |
- |
+ |
/ |
- |
- |
- |
+ |
- |
+ |
/ |
- |
- |
- |
+ |
- |
+ |
… |
- |
- |
- |
? |
- |
? |
|
- |
- |
+ |
- |
- |
+ |
|
+ |
+ |
- |
+ |
+ |
- |
|
|
+ |
+ |
+ |
+ |
+ |
+ |
|
? |
? |
? |
+/- |
? |
? |
|
+ |
+ |
? |
- |
+ |
- |
|
- |
- |
? |
+ |
- |
+ |
|
+ |
+ |
? |
+ |
+ |
? |
(Java-RMI, SOAP, REST-JSON, GraphQL)
(Java-RMI, SOAP, GraphQL)
(REST-JSON, Hadoop)
- (SQL, Hadoop)
SQL
,
(*)
/ /
/
//
… (**)
(***)
(****)
, ,
Java SQL WHERE ( )
RPC/RMI/SOAP/… ( )
( )
JAVA/Kotlin/Scala (SQL, MongoDB, REST, …)
- AST/Java/…, JAD
.
?
, Java , - .class, java , : obj.getClass()
Class , Class.getResource(‘ ’) URL .
“ , ”
, …
, ?
package xyz.cofe.trambda.l1;
import java.util.function.Function;
import org.junit.jupiter.api.Test;
public class SimpleLambdaTest {
@Test
public void javaLambda01(){
Function<Function<String,String>,String> test = (f) -> {
System.out.println("f="+f.getClass());
return null;
};
test.apply( x -> x.repeat(4) );
}
}
:
f=class xyz.cofe.trambda.l1.SimpleLambdaTest$$Lambda$235/0x0000000800142040
test-classes/ SimpleLambdaTest$$Lambda$235,
user@user-Modern-14-A10RB:00:41:32:~/code/trambda/trambda-core/target/test-classes/xyz/cofe/trambda/l1:
> ll
12
drwxrwxr-x 2 user user 4096 25 00:40 ./
drwxrwxr-x 5 user user 4096 25 00:40 ../
-rw-rw-r-- 1 user user 2162 25 00:40 SimpleLambdaTest.class
> javap -p SimpleLambdaTest.class
Compiled from "SimpleLambdaTest.java"
public class xyz.cofe.trambda.l1.SimpleLambdaTest {
public xyz.cofe.trambda.l1.SimpleLambdaTest();
public void javaLambda01();
private static java.lang.String lambda$javaLambda01$1(java.lang.String);
private static java.lang.String lambda$javaLambda01$0(java.util.function.Function);
}
- lambda$javaLambda01$1 lambda$javaLambda01$0 , ,
class Java , .
Java Serializable,
package xyz.cofe.trambda.l2;
import java.io.Serializable;
import java.util.function.Function;
public interface Fn<A,Z> extends Function<A,Z> , Serializable {
}
Runnable r = (Runnable & Serializable)() -> System.out.println("Serializable!");
Java ,
package xyz.cofe.trambda.l2;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;
import org.junit.jupiter.api.Test;
public class SerialLambdaTest {
@Test
public void serLambda01(){
Fn<Fn<String,String>,String> test = (lambda) -> {
System.out.println("lambda="+lambda.getClass());
Method writeReplace = null;
try{
writeReplace = lambda.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda sl = (SerializedLambda) writeReplace.invoke(lambda);
System.out.println(sl);
} catch( NoSuchMethodException | InvocationTargetException | IllegalAccessException e ) {
e.printStackTrace();
}
return null;
};
test.apply( x -> x.repeat(4) );
}
}
, .
lambda=class xyz.cofe.trambda.l2.SerialLambdaTest$$Lambda$235/0x0000000800142040
SerializedLambda[capturingClass=class xyz.cofe.trambda.l2.SerialLambdaTest,
functionalInterfaceMethod=xyz/cofe/trambda/l2/Fn.apply:(Ljava/lang/Object;)
Ljava/lang/Object;,
implementation=invokeStatic
xyz/cofe/trambda/l2/SerialLambdaTest.lambda$serLambda01$3fed5817$1:
(Ljava/lang/String;)Ljava/lang/String;,
instantiatedMethodType=(Ljava/lang/String;)Ljava/lang/String;, numCaptured=0]
user@user-Modern-14-A10RB:00:51:48:~/code/trambda/trambda-core/target/test-classes/xyz/cofe/trambda/l2:
> javap -p SerialLambdaTest.class
Compiled from "SerialLambdaTest.java"
public class xyz.cofe.trambda.l2.SerialLambdaTest {
public xyz.cofe.trambda.l2.SerialLambdaTest();
public void serLambda01();
private static java.lang.Object $deserializeLambda$(java.lang.invoke.SerializedLambda);
private static java.lang.String lambda$serLambda01$3fed5817$1(java.lang.String);
private static java.lang.String lambda$serLambda01$47b6c34$1(xyz.cofe.trambda.l2.Fn);
}
- $deserializeLambda$ , Serializable .
java.lang.invoke.SerializedLambda - final , ,
String getImplClass() - , .
String getImplMethodName() - .
stdout
implementation=invokeStatic xyz/cofe/trambda/l2/SerialLambdaTest.lambda$serLambda01$3fed5817$1:(Ljava/lang/String;)Ljava/lang/String;
:
private static java.lang.String lambda$serLambda01$3fed5817$1(java.lang.String);
.. -
, - , :
SerializedLambda sl = (SerializedLambda)writeReplace.invoke(lambda);
var implClassName = sl.getImplClass()
var implClassUrl =
labmda.getClass().getResource("/"+implClassName.replace(".","/")+".class");
implClassUrl -
URL
byte[] classByteCode = null;
try{
classByteCode = IOFun.readBytes(implClassUrl);
} catch( IOException e ) {
throw new IOError(e);
}
var classReader = new ClassReader(classByteCode);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
if( methName.equals(name) && descriptor!=null && descriptor.equals(methSign) ){
mdef0.set(new MethodDef(access,name,descriptor,signature,exceptions));
return dump(byteCodes::add);
}
return null;
}
};
cr.accept(cv, 0);
MethodVisior
- . , MethodDump extends MethodVisitor
:
package xyz.cofe.trambda;
public class MethodDump extends MethodVisitor implements Opcodes {
...
@Override
public void visitParameter(String name, int access){
emit(new MParameter(name,access));
}
@Override
public void visitInsn(int opcode){
emit(new MInsn(opcode));
}
...
}
visitXXXX(...) - ( )
, visitInsn( op ) new MInsn(op), emit(..)
, ( )
xyz.cofe.trambda.MethodRestore
public synchronized byte[] generate(){
//
binClassName = className.replace('.', '/');
// ClassWriter ( ASM)
// visitXXXX( op )
var cw = new ClassWriter(ClassWriter.COMPUTE_MAXS|ClassWriter.COMPUTE_FRAMES);
cw.visit(Opcodes.V11,
Opcodes.ACC_PUBLIC|Opcodes.ACC_SUPER,
binClassName,null,
"java/lang/Object", null
);
//
var mv = cw.visitMethod(
acc, // static public
name, //
desc, //
sign, // Generic
excepts); //
//
// visitXXXX()
// ,
for( var bc : byteCodes ){
if( bc instanceof MCode )build((MCode) bc);
else if( bc instanceof MEnd )build((MEnd) bc);
else if( bc instanceof MLabel )build((MLabel) bc);
else if( bc instanceof MLineNumber )build((MLineNumber) bc);
else if( bc instanceof MVarInsn )build((MVarInsn) bc);
...
}
//
return cw.toByteArray();
}
// visitCode() -
protected void build(MCode code){ mv.visitCode(); }
// visitEnd() -
protected void build(MEnd end){ mv.visitEnd(); }
protected void build(MTypeInsn tinst){
mv.visitTypeInsn(tinst.getOpcode(), tinst.getOperand());
}
,
ClassLoader
var byteCode = new MethodRestore()
.className(clName)
.methodName("lambda1")
.methodDef(mdef)
.generate();
ClassLoader cl = new ClassLoader(ClassLoader.getSystemClassLoader()) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException{
if( name!=null && name.equals(clName) ){
return defineClass(name,byteCode,0,byteCode.length);
}
return super.findClass(name);
}
};
System.out.println("try read class "+clName);
Class c = null;
try{
c = Class.forName(clName,true,cl);
System.out.println("class found "+c);
} catch( ClassNotFoundException e ) {
e.printStackTrace();
return;
}
Method m = null;
System.out.println("methods");
for( var delMeth : c.getDeclaredMethods() ){
System.out.println(""+delMeth);
if( delMeth.getName().equals(methName) ){
m = delMeth;
}
}
try{
Object arg0 = "abc";
System.out.println("call with "+arg0);
Object res = m.invoke(null, arg0);
System.out.println("result "+res);
} catch( IllegalAccessException | InvocationTargetException e ) {
e.printStackTrace();
}
Kotlin , .. Kotlin , Scala
(Groovy, JavaScript) - , AST - , .
- - ,
Potentiellement sur le client, Java peut être plus récent, avec un bytecode différent de celui du serveur, le serveur peut ne pas connaître les constructions du nouveau Java
La bibliothèque ne transfère pas tout le code d'octet, cela est dû au fait que tout le code d'octet n'a pas de représentation d'objet - c'est probablement une question à résoudre, une question de raffinement.
Séparément - c'est une question de transmission réseau
Problème de sécurité - techniquement, il peut être résolu, mais il faut terminer avec un fichier
Le protocole de transfert, ma bibliothèque utilise TCP, mais cette couche réseau peut toujours être changée pour une couche plus appropriée pour vous, mais bien sûr elle nécessitera sa mise en œuvre, en fait, la sérialisation du lambda et sa récupération ne limitent pas le réseau couche de quelque manière que ce soit.