当前位置: 首页 > news >正文

c没有main函数/java没有main方法--语言运行的实质之实例

前面我们看到,没有main的代码也能执行,之所以拥有main是为了遵循一种规定,遵循这个规定得到的益处是一切更加紧凑,数据冗余更小,程序更好维护,系统更好维护...如果抛开这些不谈,代码的编写其实是很灵活的,完全不需要遵循任何的附加规定,所需要遵循的只是冯氏机器的执行流程。本文就来整一套没有main的c代码和java代码的混合,旨在揭示代码运行的深层含义以及c语言和java语言的启动和层次关系。我们按一个操作步骤一步一步来:
1.准备没有main方法但是期望成为java主类的类文件-Test.java
class Test {
public native void Wrapper();
static {
System.loadLibrary("from-java");
}
public static void sub(String[] args) {
new TestStunnel().Wrapper();
}
}
编译之:javac Test.java
并且用c实现一个so,实现Wrapper方法,它可以是stunnel,可以是openvpn,只需要将其main函数改为Wrapper并且编译成so而不是可执行文件即可!
2.准备一个汇编文件-loader.asm,它负责直接接管sys_execve内核系统调用返回用户态的第一时间的执行流:
global _start
extern not_main
section .text
_start:
call not_main
ret
用nasm编译之:nasm -f elf loader.asm
3.准备一个c文件-startjvm.c,它启动java虚拟机,并且执行java方法:
#include <jni.h>
#include <stdio.h>
int not_main() {
JavaVM *vm;
JNIEnv *env;
... //见上篇的代码或者直接参考java.c
}
用gcc编译之:gcc -c startjvm.c -I<jdk的include和include/linux目录>
4.将上述的链接在一起:gcc -nostartfiles startjvm.o loader.o <jre的jvm动态库路径>/libjvm.so -o no_main_main
必须使用-nostartfiles,因为只有这样,编译器才不会自动加入启动函数以及别的库级别的初始化,才不会调用标准链接器的_start,关于这个你可以通过ld --verbose来观看!
5.执行吧:./no_main_main
6.结果Wrapper被调用,整个过程完全自给掌控,没有main函数,也没有main方法!
7.有一种更方便的不调用main的方式,那就是gcc指定-e参数,后面跟你希望执行的函数名称,这样虽然能达到一定的效果,但是估计你除了多学习了一个gcc参数之外,什么也学不到。
8.整个过程中我们把所有的逻辑往下压了一层,c语言中不再从语言机制的main开始,而是从链接器机制的_start开始,java语言中不再以语言机制的main开始,而是从jvm的GetStaticMethodID和随后的CallStaticVoidMethod开始。

相关文章:

  • 深有体会内存对系统性能的重要性
  • 判断括号的匹配性的一种算法
  • 焦点图下面的索引小圆环
  • java虚拟机的启动实例--eclipse的方式
  • 本地方法中printf如何传给java--java系统级命名管道
  • OUYA游戏开发核心技术剖析大学霸内部资料
  • 解决windows 10 9926 中vmware安装的虚拟机无法桥接上网的问题
  • 字符设备驱动程序
  • html中#include file的使用方法
  • 天龙客户端的ResourceManager
  • 我想改了我的音箱
  • sql server 中引號嵌套
  • jsfDemo
  • 第二章
  • 【转】风雨20年:我所积累的20条编程经验
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • [译]前端离线指南(上)
  • 【前端学习】-粗谈选择器
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Angular Elements 及其运作原理
  • git 常用命令
  • Map集合、散列表、红黑树介绍
  • NSTimer学习笔记
  • Python打包系统简单入门
  • Python实现BT种子转化为磁力链接【实战】
  • Redis学习笔记 - pipline(流水线、管道)
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 对JS继承的一点思考
  • 构建二叉树进行数值数组的去重及优化
  • 码农张的Bug人生 - 见面之礼
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 树莓派 - 使用须知
  • 系统认识JavaScript正则表达式
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​TypeScript都不会用,也敢说会前端?
  • #if和#ifdef区别
  • #QT(一种朴素的计算器实现方法)
  • (23)Linux的软硬连接
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (编译到47%失败)to be deleted
  • (翻译)terry crowley: 写给程序员
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (数据结构)顺序表的定义
  • (一)UDP基本编程步骤
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)编辑寄语:因为爱心,所以美丽
  • (转)负载均衡,回话保持,cookie
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .net core使用ef 6