[Java]_[中级]_[使用okhttp3和HttpClient代理访问外部网络]
场景
Java
的http
库常用的有HttpClient
和Okhttp3
, 如果公司有限制网络访问,需要代理才可以访问外网,那么如何使用代理Proxy
?
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.14.9</version>
</dependency>
说明
-
从性能方面来说,
Okhttp3
更出色一点。因为从我本机运行两个库的访问,Okhttp3
会快一些。 -
从易用性来说,
Ohttp3
更好。OkHttpClient
只需要在Builder
里调用proxy(Proxy)
传递一个Proxy
对象之后即可。之后访问其他外网,就直接创建外网的Request
即可,非常方便。 代理和非代理都用统一的方法。OkHttpClient.Builder builder = client.newBuilder(); builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostName, Integer.parseInt(hostPort))));... Response response = getClient().newCall(request).execute()
-
HttpClient
访问[1]则需要创建两个对象: 需要访问的主机HttpHost
和URL里的请求路径和查询参数的HttpGet
对象。 每次请求都需要传递这两个参数。而如果非代理的话,就需要调用另外的重载方法。HttpHost target = HttpHost.create(hostUrl); HttpGet request = new HttpGet("/user?name=xxx"); // HttpGet httpGet = new HttpGet(hostUrl); // 非代理... httpClient.execute(target, request) // 代理 // httpClient.execute(httpGet); // 非代理
-
注意,出于创建
Client
比较废资源,okhttp3
还是HttpClient
官方都是推荐创建单例的OkHttpClient
和HttpClient
对象来使用。对于CloseableHttpClient
在使用完之后还需要调用close()
关闭。OkHttpClient
官方例子也没有调用销毁方法。 -
从源码设计上来说,
Okhttp3
在发送数据时,使用了自带的线程池,我们想用自己的线程池代替都不行。这个对某些线程数有严格限制的程序(Linux)非常不友好,甚至不能用,因为它的线程不受宿主程序控制。// 在类 RealConnectionPool里有这段代码 static {executor = new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue(), Util.threadFactory("OkHttp ConnectionPool", true)); }
例子
- 以下是使用
okhttp3
和HttpClient
的目前最佳做法.
OkHttpClientCaller
import Pair;
import StringUtils;
import HttpHelper;
import okhttp3.*;
import org.apache.log4j.Logger;import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Map;public class OkHttpClientCaller {private static Logger logger = Logger.getLogger(OkHttpClientCaller.class);private static OkHttpClient client;public static void newClient(){OkHttpClient.Builder builder = new OkHttpClient().newBuilder();client = builder.cookieJar(new LocalCookieJar()).build();}public static void setProxy(String hostName,String hostPort){Proxy proxy = client.proxy();if(StringUtils.isEmpty(hostName,hostPort)){if(proxy != null) {client.newBuilder().proxy(null).cookieJar(new LocalCookieJar()).build();}}else{if(proxy == null){OkHttpClient.Builder builder = client.newBuilder();builder.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostName, Integer.parseInt(hostPort))));client = builder.cookieJar(new LocalCookieJar()).build();}}}public static OkHttpClient getClient(){return client;}public static Pair<Boolean,String> doGet(Map<String,String> hostHeaders,String hostUrl){Request.Builder builder = new Request.Builder().url(hostUrl);HttpHelper.buildRequestHeader(builder,hostHeaders);Request request = builder.get().build();try (Response response = getClient().newCall(request).execute()) {return new Pair<>((response.code() == 200), response.body().string());} catch (Exception e) {logger.error(e.getMessage());}return new Pair<>(false,"");}/**** @param apiUrl* @param apiHeaders* @param contentType "application/x-www-form-urlencoded" "application/json"* @param content* @return*/public static Pair<Boolean,String> doPost(String apiUrl,Map<String,String> apiHeaders,String contentType,String content){// HeaderRequest.Builder builder = new Request.Builder().url(apiUrl);HttpHelper.buildRequestHeader(builder,apiHeaders);MediaType mediaType = MediaType.parse(contentType);RequestBody body = RequestBody.create(mediaType,content);// Posttry(Response response = getClient().newCall(builder.post(body).build()).execute()){return new Pair<>((response.code() == 200), response.body().string());} catch (IOException e) {logger.error(e.getMessage());}return new Pair<>(false,"");}public static Pair<Boolean,String> doPostFormData(String apiUrl,Map<String,String> apiHeaders,String content){return doPost(apiUrl,apiHeaders,"application/x-www-form-urlencoded",content);}public static Pair<Boolean,String> doPostJsonData(String apiUrl,Map<String,String> apiHeaders,String content){return doPost(apiUrl,apiHeaders,"application/json",content);}
}
HttpClientCaller
import Pair;
import StringUtils;
import RequestUtils;
import HttpHelper;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;import static RequestUtils.getPathAndQueryParam;
import static RequestUtils.getPort;public class HttpClientCaller {private static Logger logger = Logger.getLogger(HttpClientCaller.class);private static CloseableHttpClient httpClient;private static RequestConfig requestConfig;//传输超时时间, 10秒private static int socketTimeout = 10000;//建立连接超时时间,默认10秒private static int connectTimeout = 5000;//获取连接超时时间,10秒private static int connectRequest = 5000;private static HttpHost proxy = null;private static HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {@Overridepublic boolean retryRequest(IOException exception,int executionCount, HttpContext context) {return false;}};public static CloseableHttpClient createClientAttr(HttpClientBuilder builder){return builder.setRetryHandler(myRetryHandler).setMaxConnPerRoute(2).setMaxConnTotal(2).build();}public static void newClient() {// setMaxConnTotal是连接池中可用的总最大连接数。setMaxConnPerRoute是限制到单个端口或url的连接总数。httpClient = createClientAttr(HttpClients.custom());//根据默认超时限制初始化requestConfigrequestConfig = getCommonRequestConfigBuilder().build();}public static RequestConfig.Builder getCommonRequestConfigBuilder(){RequestConfig.Builder builder = RequestConfig.custom().setConnectionRequestTimeout(connectRequest).setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout);return builder;}/*** 不行: https://blog.csdn.net/woshirongshaolin/article/details/126992654* @return*/public static SSLConnectionSocketFactory createSSLFactory(){//使用 loadTrustMaterial() 方法实现一个信任策略,信任所有证书try {SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {// 信任所有public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {return true;}}).build();//NoopHostnameVerifier类: 作为主机名验证工具,实质上关闭了主机名验证,它接受任何//有效的SSL会话并匹配到目标主机。HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);return sslsf;} catch (NoSuchAlgorithmException e) {logger.error(e.getMessage());} catch (KeyManagementException e) {logger.error(e.getMessage());} catch (KeyStoreException e) {logger.error(e.getMessage());}return null;}/**** @param hostName* @param port*/public static void setProxy(String hostName,String port){// 不支持// https://github.com/apache/httpcomponents-client/blob/4.5.x/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteProxy.javaif(StringUtils.isEmpty(hostName,port)){if(proxy != null)requestConfig = getCommonRequestConfigBuilder().setProxy(null).build();}else{if(proxy == null){closeClient();SSLConnectionSocketFactory sslFactory = createSSLFactory();if(sslFactory != null)httpClient = createClientAttr(HttpClients.custom().setSSLSocketFactory(sslFactory));proxy = new HttpHost(hostName, Integer.parseInt(port));requestConfig = getCommonRequestConfigBuilder().setProxy(proxy).build();}}}public static void closeClient(){try {if(httpClient != null)httpClient.close();httpClient = null;} catch (Exception e) {e.printStackTrace();}}public static RequestConfig getRequestConfig(){return requestConfig;}public static CloseableHttpClient getClient(){return httpClient;}public static Pair<Boolean,String> doGet(Map<String,String> hostHeaders, String hostUrl){if(proxy != null){URL url = RequestUtils.getUrlOrNull(hostUrl);HttpHost target = new HttpHost(url.getHost(), getPort(url),url.getProtocol());HttpGet request = new HttpGet(getPathAndQueryParam(url));request.setConfig(requestConfig);HttpHelper.buildRequestHeader(request,hostHeaders);try(CloseableHttpResponse response = httpClient.execute(target, request);){return new Pair<>((response.getStatusLine().getStatusCode() == 200),EntityUtils.toString(response.getEntity(), "utf-8"));}catch ( IOException e){e.printStackTrace();}}else{HttpGet httpGet = new HttpGet(hostUrl);httpGet.setConfig(requestConfig);HttpHelper.buildRequestHeader(httpGet,hostHeaders);try(CloseableHttpResponse response = httpClient.execute(httpGet);){return new Pair<>((response.getStatusLine().getStatusCode() == 200),EntityUtils.toString(response.getEntity(), "utf-8"));}catch ( IOException e){e.printStackTrace();}}return new Pair<>(false,"");}public static Pair<Boolean,String> doPost(String apiUrl,Map<String,String> apiHeaders,String contentType,String content) {if(proxy != null){URL url = RequestUtils.getUrlOrNull(apiUrl);HttpHost target = new HttpHost(url.getHost(), getPort(url),url.getProtocol());HttpPost post = new HttpPost(getPathAndQueryParam(url));HttpHelper.buildRequestHeader(post,apiHeaders);if(post.getFirstHeader("Content-Type") == null)post.addHeader("Content-Type",contentType);StringEntity postEntity = new StringEntity(content, "UTF-8");post.setEntity(postEntity);post.setConfig(requestConfig);try(CloseableHttpResponse response = httpClient.execute(target,post)){return new Pair<>((response.getStatusLine().getStatusCode() == 200),EntityUtils.toString(response.getEntity(), "utf-8"));} catch (IOException e) {logger.warn(e.getMessage());}}else{HttpPost post = new HttpPost(apiUrl);HttpHelper.buildRequestHeader(post,apiHeaders);if(post.getFirstHeader("Content-Type") == null)post.addHeader("Content-Type",contentType);StringEntity postEntity = new StringEntity(content, "UTF-8");post.setEntity(postEntity);post.setConfig(requestConfig);try(CloseableHttpResponse response = httpClient.execute(post)){return new Pair<>((response.getStatusLine().getStatusCode() == 200),EntityUtils.toString(response.getEntity(), "utf-8"));} catch (IOException e) {logger.warn(e.getMessage());}}return new Pair<>(false,"");}public static Pair<Boolean,String> doPostFormData(String apiUrl,Map<String,String> apiHeaders,String content){return doPost(apiUrl,apiHeaders,"application/x-www-form-urlencoded; charset=UTF-8",content);}public static Pair<Boolean,String> doPostJsonData(String apiUrl,Map<String,String> apiHeaders,String content){return doPost(apiUrl,apiHeaders,"application/json; charset=UTF-8",content);}
}
HttpHelper
import okhttp3.Request;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.message.AbstractHttpMessage;import java.util.Map;public class HttpHelper {public static void buildRequestHeader(AbstractHttpMessage builder, Map<String,String> values){for (Map.Entry<String,String> keyValue:values.entrySet()) {builder.addHeader(keyValue.getKey(),keyValue.getValue());}}public static void buildRequestHeader(Request.Builder builder,Map<String,String> values){for (Map.Entry<String,String> keyValue:values.entrySet()) {builder.addHeader(keyValue.getKey(),keyValue.getValue());}}public static String toFormData(Map<String,String> params){StringBuilder sb = new StringBuilder();for (Map.Entry<String,String> keyValue: params.entrySet())sb.append(keyValue.getKey()).append("=").append(keyValue.getValue()).append("&");if(sb.length() > 0)return sb.substring(0,sb.length()-1);return "";}
}
RequestUtils
import java.net.MalformedURLException;
import java.net.URL;public class RequestUtils {/**** @param url* @return URL or null*/public static URL getUrlOrNull(String url){try {return new URL(url);} catch (MalformedURLException e) {e.printStackTrace();}return null;}public static int getPort(URL url){int port = url.getPort();return (port == -1)?url.getDefaultPort():port;}public static String getPathAndQueryParam(URL url){String path = url.getPath();String query = url.getQuery();if(query == null)return path;return String.format("%s?%s",path,query);}
}
运行
OkHttpClientCaller.newClient();
OkHttpClientCaller.setProxy("127.0.0.1","1283");
Pair<Boolean, String> pp = OkHttpClientCaller.doGet(headers, "https://www.bing.com");
if(pp.k)logger.info(pp.v);OkHttpClientCaller.closeClient();
参考
-
httpcomponents-client/httpclient/src/examples/org/apache/http/examples/client/ClientExecuteProxy.java
-
Httpclient3.1指定tlsv1.2协议访问https
-
java http请求设置代理 Proxy_java
-
RestTemplate发起HTTPS请求Unsupported or unrecognized SSL message
-
HttpClient访问不安全的https链接报错:SSLHandshakeException
-
httpclient信任所有证书解决SSLException:Unrecognized SSL message
-
Java URI getQuery()方法及示例
相关文章:
[Java]_[中级]_[使用okhttp3和HttpClient代理访问外部网络]
场景 Java的http库常用的有HttpClient和Okhttp3, 如果公司有限制网络访问,需要代理才可以访问外网,那么如何使用代理Proxy? <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient<…...
ubuntu 20.04 docker 安装 mysql
要在Ubuntu 20.04上安装Docker并运行MySQL容器,您可以按照以下步骤操作: 1.更新系统包列表: sudo apt update2.安装Docker: sudo apt install docker.io3.启动Docker服务并设置其开机自启动: sudo systemctl start…...

C++在C语言基础上的优化
目录 一、命名空间 1、命名空间的定义 2、命名空间的使用 二、输入&输出 三、缺省参数 1、缺省参数的概念 2、缺省参数的分类 四、函数重载 五、引用 1.引用的概念 2.引用的特性 3、引用和指针的区别 六、内联函数 七、基于范围的for循环 一、命名空间 命名空…...

分享一个python实验室设备预约管理系统 实验室设备维修系统源码 lw 调试
💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…...

兵者多诡(HCTF2016)
环境:https://github.com/MartinxMax/CTFer_Zero_one 题目简介 解题过程 登录首页 提交png图片上传抓包,可以看到是向upload文件提交数据 在fp参数中尝试伪协议读取home.php文件 http://127.0.0.1:88/HCTF2016-LFI/home.php?fpphp://filter/readconvert.base64…...

【JAVA-Day04】Java关键字和示例:深入了解常用关键字的用法
Java关键字和示例:深入了解常用关键字的用法 摘要Java 关键字、标识符和命名规范一、Java 关键字常用关键字DEMO1. 示例代码使用 if 和 else 关键字:2. 示例代码使用 for 循环:3. 示例代码使用 switch 关键字:4. 示例代码使用 wh…...
Android请求网络报错:not permitted by network security policy
一、错误记录 https的接口请求正常的, 请求http的接口时报错:not permitted by network security policy 二、问题分析 原因: 由于 Android P(版本27以上) 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉。如果当…...
python报错:ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1
python报错:ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1 问题分析 说明:requests包引入了urllib3,而新版本的urllib3 需要OpenSSL 1.1.1以上版本,否则报错: ImportError: urllib3 v2.0 only supports Ope…...
如何使用adb command来设置cpu频率和核数
透過ADB Shell設定CPU開核與freq的command與用法如下: # Disable PPM echo 0 > /proc/ppm/enabled # Enable PPM (Default) echo 1 > /proc/ppm/enabled echo 0 > /proc/ppm/enabled Fixed # Core for each cluster echo X Y > /proc/ppm/policy/ut_fix_core_num …...

236. 二叉树的最近公共祖先
236. 二叉树的最近公共祖先 题目-中等难度示例1. dfs 题目-中等难度 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p…...
Git常见问题:git pull 和 git pull --rebase二者区别
git pull 和 git pull --rebase 都是从远程仓库获取最新的更改并将其合并到本地分支。但它们之间的区别在于合并方式。以下是它们之间的主要区别: git pull: 当你执行 git pull 时,Git 会执行以下两个操作: git fetchÿ…...

关于HarmonyOS元服务的主题演讲与合作签约
一、感言 坚持中,总会有很多意想不到的收获。 前几次参与HDC时更多的是观众、开发者、专家的身份,以参观、学习、交流为主。 通过几年的努力,和HarmonyOS功能成长,在2023年的HDC大会中,有了我的演讲,并带领…...
cache 学习
好文章: Cache的基本原理 - 知乎...

SSM - Springboot - MyBatis-Plus 全栈体系(六)
第二章 SpringFramework 四、SpringIoC 实践和应用 3. 基于 注解 方式管理 Bean 3.1 实验一:Bean 注解标记和扫描 (IoC) 3.1.1 注解理解 和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框…...

【Flutter】引入网络图片时,提示:Failed host lookup: ‘[图片host]‘
在使用 NetworkImage 组件加载外部图片时,提示 Failed host lookup: [图片host] 错误。 排查方向 1、清理缓存 解决方案: 尝试flutter clean清空缓存后重新安装依赖flutter pub get重新构建项目flutter create . 走完上述三个步骤后,再次…...

Python基础教程:索引和切片
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 索引(下标) 索引又称下标,用来表示可迭代对象中的某个元素的位置。 用正整数表示的索引值,从左向右定位,从 0 开始计数,如 0,1&#…...

JVM基础面试题
JDK、JRE、JVM的关系 JVM Java虚拟机,它只识别.class类型文件,它能将class文件中的字节码指令进行识别并调用操作系统向上的API完成动作。 JRE Java运行时环境。它主要包含两部分:Jvm的标准实现和Java的一些基本类库。相对于JVM来说,JRE多出来…...
蓝桥杯官网填空题(平方末尾)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 能够表示为某个整数的平方的数字称为“平方数” 虽然无法立即说出某个数是平方数,但经常可以断定某个数不是平方数。 因为平方数的末位只可能是&#x…...

深入探究数据结构与算法:构建强大编程基础
文章目录 1. 为什么学习数据结构与算法?1.1 提高编程技能1.2 解决复杂问题1.3 面试准备1.4 提高代码效率 2. 学习资源2.1 经典教材2.2 在线学习平台2.3 学习编程社区 3. 数据结构与算法的实际应用3.1 排序算法3.2 图算法3.3 字符串匹配算法 4. 结论 🎉欢…...

Android 自定义View之圆形进度条
很多场景下都用到这种进度条,有的还带动画效果, 今天我也来写一个。 写之前先拆解下它的组成: 底层圆形上层弧形中间文字 那我们要做的就是: 绘制底层圆形;在同位置绘制上层弧形,但颜色不同ÿ…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...